目录
$ sudo grep -n "main" setup.py
0,基本bash shell命令
- /etc/passwd文件
该文件包含了系统所有账户列表以及每个用户的基本配置信息,如下图所示:
每条记录有七个字段,之间用:隔开,格式如下:
登录用户名:用户密码:用户账户的UID:用户账户的组ID(GID):备注字段:用户HOME目录位置:用户的默认shell。
Linux会为各种各样的功能创建不同的用户账户,称之为系统账户,这些账户不是真正的用户,是系统上运行的进程访问资源的特殊账户。所有在后台运行的服务都需要用一个系统账户登录到Linux系统上。密码字段被设置成了x,表明密码不在此文件中,所有的用户密码被保存在/etc/shadow文件中。
2. /etc/shadow文件
该文件信息截图如下:
在/etc/shadow文件中每条记录有9个字段,分别是:
与/etc/passwd文件中登录名字段对应的登录名:加密后的密码:自上次修改密码后过去的天数(加密了):多少天后才能更改密码:多少天后必须更改密码:密码过期前提前多少天提醒用户更改密码:密码过期后多少天禁用账户:用户账户被禁用的日期:预留字段。
3.bash手册以及man命令
man命令用来访问存储在Linux系统上的手册页面。
手册页的结构安排如上图所示。可以看出,手册页由9个内容区域构成(这些内容区域不一定都存在)。man命令只查询了ls手册页内容区域1,要想查询其他内容区域需要使用man section# topic。手册页的每个内容区域有18个小节(这些小节不一定都存在),每个小节有惯用的命名标准,如下所示:
遍历目录以及cd、pwd命令
cd:切换目录
pwd:显示当前目录
单点符(.):当前目录
双点符(..):当前目录的父目录
制表键自动补全:使用制表键自动补全要给shell足够的文件信息。
下载命令
yum主要安装linux系统的中的软件应用,例如nginx,haproxy,mysql等等
pip安装python中的模块,由于python需要安装相当多的模块,可以使用pip 安装,pip可以使用install语句安装模块,可以升级模块,并且可以删除你之前所安装的模块。
1,ls,touch,mkdir
ls:显示当前目录下的文件和目录
ls -F:显示当前目录下的文件和目录,并且可以进行区分
ls -a:显示当前目录下的所有文件和目录,包括隐藏文件也会被显示出来
ls -R:显示当前目录下的文件和目录、子目录下的文件和目录、子子目录下的文件和目录...
ls -l: 以长列表的形式显示当前目录下的文件和目录
ls 字符串:过滤输出列表。ls能够识别标准通配符,并在过滤器中使用它们进行模式匹配。标准通配符为:
问号(?):代表一个字符
星号(*):代表零个或者多个字符
//创建文件
touch 11111.txt
//创建隐藏文件
touch .22.txt
//创建文件夹
mkdir 222
//列出文件和隐藏文件
ls -a
//以列表形式显示
ls -l
//以列表显示文件时,以合适的单位来显示
ls -l -h
//以2开头的所有文件
ls 2*
//以2开头的,后面必须只有一位的文件(一个?只表示一位)
ls 2?
//顺序不唯一,结果都一样
ls -l -h -a <======>ls -alh
//tab键可自动补全较长的文件名
//查看一个文件内部内容
cat xxxxx
//可编辑文件
gedit
2,复制文件cp & scp
2.1 说明
cp:是在同一个linux系统上,在不同的目录之间复制文件;
scp:是在不同linux系统之间来回复制文件;
cp src dst:
若src和dst同是文件,cp将src文件复制成一个新文件,并且以dst命名;
若src是文件,dst是目录,将src文件复制到dst目录下;
若src是目录,dst是目录,使用参数R可以将src目录中的内容复制到dst目录下。
cp命令也可以使用通配符。
2.2 用法cp
单个文件复制:
cp 源文件 目标路径 ~~从原路径复制源文件到目标路径下;如果在目标路劲之后加文件名称和格式意思就是复制过去之后将该文件重命名。
多个文件复制:
cp 源文件1 源文件2 源文件3 ... 目标路径 ~~从原路径复制源文件到目标路径下;
cp 的参数详解
-a 尽可能将源文件状态、权限等资料都照原装予以复制,并且是递归copy;
-r 表示递归copy,若source中含有目录名,则将目录下之档案亦皆依序拷贝至目的地;
-f 若目的地已经有相同档名的档案存在,则在复制前先予以删除再行复制;
2.3 scp用法
基本语法:scp [参数] 文件 @IP:/目标路径;如下图
scp参数详解
-1 强制scp命令使用协议ssh1
-2 强制scp命令使用协议ssh2
-4 强制scp命令只使用IPv4寻址
-6 强制scp命令只使用IPv6寻址
-B 使用批处理模式(传输过程中不询问传输口令或短语)
-C 允许压缩。(将-C标志传递给ssh,从而打开压缩功能)
-p 保留原文件的修改时间,访问时间和访问权限。
-q 不显示传输进度条。
-r 递归复制整个目录。
-v 详细方式显示输出。scp和ssh(1)会显示出整个过程的调试信息。这些信息用于调试连接,验证和配置问题。
-c cipher 以cipher将数据传输进行加密,这个选项将直接传递给ssh。
-F ssh_config 指定一个替代的ssh配置文件,此参数直接传递给ssh。
-i identity_file 从指定文件中读取传输时使用的密钥文件,此参数直接传递给ssh。
-l limit 限定用户所能使用的带宽,以Kbit/s为单位。
-o ssh_option 如果习惯于使用ssh_config(5)中的参数传递方式,
-P port 注意是大写的P, port是指定数据传输用到的端口号
-S program 指定加密传输时所使用的程序。此程序必须能够理解ssh(1)的选项。
例:scp -r 文件夹 @IP:目标路径;
3,ps命令和探查进程
默认情况下,ps命令会显示当前控制台下属于当前用户的进程,如
Linux系统中ps命令支持3种不同风格的命令行参数:Unix风格、BSD风格和GNU风格。
可以使用Unix风格下的-ef参数显示系统上运行的所有参数:
UID:启动进程的用户
PID:进程ID
PPID:父进程的进程号
C:进程生命周期中CPU的利用率
CMD :启动的程序名称
4,top命令和实时监测进程
使用top命令能够实时显示进程状态,如下所示
其中13min代表系统运行的时间,1user代表登录的用户数,平均负载:最近1min、最近5min、最近15min。zombie代表进程处于僵化状态(进程完成了,但是父进程没有响应)。第三行表明了cpu的概要信息,第四和第五行显示了系统内存的状态。最后是进程的详细列表。
PR:进程的优先级
NI:进程的谦让度值
VIRT:进程占用的虚拟内存总量
RES:进程占用的物理内存总量
SHR:进程和其他进程共享的内存总量
S:进程的状态(T代表跟踪状态或者停止状态,Z代表僵化状态)
COMMAND:进程所对应的命令行名称,也就是启动的程序名
5,挂载存储媒体与mount命令
mount命令输出如下:
sysfs:媒体的设备文件名
/sys:媒体挂在到虚拟目录的挂载点
type sysfs:文件系统类型
(rw):已挂载媒体的访问状态
6,df命令查看磁盘空间
df命令输出如下:
udev:设备的文件位置
1976780:能容纳多少1024字节大小的块
7,排序数据与sort命令
sort命令默认会按照字符串的排序对文本文件中的数据进行排序,-n参数用来对数字进行排序,-M参数对日期进行排序
8, 搜索数据与grep命令
你是否遇到过需要在文件中查找一个特定的字符串或者样式,但是不知道从哪儿开始?那么,就请grep来帮你吧
1.搜索和寻找文件
假设你已经在你的电脑上安装了一个全新的Ubuntu,然后你打算卸载Python。你浏览网页寻找教程,但是你发现存在两个不同版本的Python在使用,而你不知道你的Ubuntu安装器到底在你的系统中安装了哪个版本的Python,也不知道它安装了哪些模块。解决这个烦恼只需简单的运行以下命令:
$ sudo dpkg -l | grep -i python
输出例子
ii python2.7 2.7.3-0ubuntu3.4 Interactive high-level object-oriented language (version 2.7)
ii python2.7-minimal 2.7.3-0ubuntu3.4 Minimal subset of the Python language (version 2.7)
ii python-openssl 0.12-1ubuntu2.1 Python wrapper around the OpenSSL library
ii python-pam 0.4.2-12.2ubuntu4 A Python interface to the PAM library
首先,我们运行dpkg -l列出你系统上安装的.deb包。接着,我们使用管道将输出结果传输给命令grep -i python,这一步可以简单解释为把结果传输给grep然后过滤出所有含有python的项,并返回结果。–i选项用于忽略大小写,因为 grep 是大小写敏感的。使用选项-i是个好习惯,除非你打算进行更细节的搜索。
2.搜索和过滤文件
grep还可以在一个或多个文件里用于搜索和过滤。让我们来看一个这样的情景:
你的Apache网页服务器出现了问题,你不得不从许多专业网站里找一个发帖询问。好心回复你的人让你粘贴上来你的/etc/apache2/sites-available/default-ssl文件内容。假如你能移除掉所有的注释行,那么对你,对帮你的人,以及所有阅读该文件的人,不是更容易发现问题吗?你当然可以很容易的做到!只需这样做就可以了:
$ sudo grep -v "#" /etc/apache2/sites-available/default-ssl
选项-v是告诉grep命令反转它的输出结果,意思就是不输出匹配的项,做相反的事,打印出所有不匹配的项。这个例子中,有#的是注释行(译注:其实这个命令并不准确,包含“#”的行不全是注释行。关于如何精确匹配注释行,可以了解更多的关于正则表达式的内容。)
3.找出所有的mp3文件
grep命令对于过滤来自于标准输出的结果非常有用。例如,假设你的一个文件夹里面全是各种格式的音乐文件。你要找出艺术家jayZ的所有mp3格式的音乐文件,里面也不要有任何混合音轨。使用find命令再结合管道使用grep就可以完成这个魔法:
$ sudo find . -name ".mp3" | grep -i JayZ | grep -vi "remix""
在这个例子中,我们使用find命令打印出所有以.mp3为后缀名的文件,接着将其使用管道传递给grep -i过滤和打印出名字为“JayZ”的文件,再使用管道传送给grep -vi以便过滤掉含有“remix”的项。
4.在搜索字符串前面或者后面显示行号
另外两个选项是-A和-B之间的切换,是用以显示匹配的行以及行号,分别控制在字符串前或字符串后显示的行数。Man页给出了更加详细的解释,我发现一个记忆的小窍门:-A=after、-B=before。
$ sudo ifconfig | grep -A 4 etho $ sudo ifconfig | grep -B 2 UP
5.在匹配字符串周围打印出行号
grep命令的-C选项和例4中的很相似,不过打印的并不是在匹配字符串的前面或后面的行,而是打印出两个方向都匹配的行(译注:同上面的记忆窍门一样:-C=center,以此为中心): $ sudo ifconfig | grep -C 2 lo
6.计算匹配项的数目
这个功能类似于将grep输出的结果用管道传送给计数器(wc程序),grep内建的选项可以达到同样的目的:
$ sudo ifconfig | grep -c inet6
7.按给定字符串搜索文件中匹配的行号
当你在编译出错时需要调试时,grep命令的-n选项是个非常有用的功能。它能告诉你所搜索的内容在文件的哪一行:
$ sudo grep -n "main" setup.py
8.在所有目录里递归的搜索
假若你要在当前文件夹里搜索一个字符串,而当前文件夹里又有很多子目录,你可以指定一个-r选项以便于递归的搜索: $ sudo grep -r “function” *
9.进行精确匹配搜索
传递-w选项给grep命令可以在字符串中进行精确匹配搜索(译注:包含要搜索的单词,而不是通配)。例如,像下面这样输入:
$ sudo ifconfig | grep -w “RUNNING”
将打印出含有引号内匹配项的行。另外,你还可以试一下这个:
$ sudo ifconfig | grep -w “RUN”
搜索这个匹配项时,若搜索的东西里面没有这样的一个单独的单词,将什么也不会返回。
10.在Gzip压缩文件中搜索
我们还要关注一下grep的衍生应用。第一个是zgrep,这个与zcat很相似,可以用于gzip压缩过的文件。它有与grep相似的命令选项,使用方式也一样:
$ sudo zgrep -i error /var/log/syslog.2.gz
11.在文件中匹配正则表达式
egrep是另一个衍生应用,代表着“扩展全局正则表达式”。它可以识别更多的正则表达式元字符,例如at + ? | 和()。在搜索源代码文件时,egrep是一个非常有用的工具,还有其他的一些零碎代码文件的搜索需要,使得这样的搜索能力成为必需。可以在grep命令中使用选项-E来启用它。
$ sudo grep -E
12.搜索一个固定匹配字符串
fgrep用于在一个文件或文件列表中搜索固定样式的字符串。功能与grep -F同。fgrep的一个通常用法为传递一个含有样式的文件给它:
$ sudo fgrep -f file_full_of_patterns.txt file_to_search.txt
9,cat命令
“ concatenate ”的缩写:连锁的,串联的
1.显示文件内容
在下面的示例中,它将显示/ etc / passwd文件的内容。
# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
narad:x:500:500::/home/narad:/bin/bash
2.在终端中查看多个文件的内容
在下面的示例中,它将在终端中显示test和test1文件的内容。
# cat test test1
Hello everybody
Hi world,
3.使用Cat命令创建文件
我们将使用以下命令创建一个名为test2文件的文件。
# cat >test2
等待用户输入,键入所需的文本,然后按CTRL + D(按住Ctrl键并键入“ d ”)退出。文本将写入test2文件中。您可以使用以下cat命令查看文件的内容。
# cat test2
hello everyone, how do you do?
4.将Cat命令与更多或更少的选项一起使用
如果具有大量内容的文件无法容纳在输出终端中,并且屏幕快速滚动,则可以通过cat命令使用越来越多的参数,如上所示。
# cat song.txt | more
# cat song.txt | less
5.在文件中显示行号
使用-n选项,您可以在输出终端中看到文件song.txt的行号。
# cat -n song.txt
1 "Heal The World"
2 There's A Place In
3 Your Heart
4 And I Know That It Is Love
5 And This Place Could
6 Be Much
7 Brighter Than Tomorrow
8 And If You Really Try
9 You'll Find There's No Need
10 To Cry
11 In This Place You'll Feel
12 There's No Hurt Or Sorrow
6.在文件末尾显示$
在下面,您可以使用-e选项看到' $ '出现在行尾,如果各段之间有间隙,则显示' $ '。此选项对于将多行压缩为一行很有用。
# cat -e test
hello everyone, how do you do?$
$
Hey, am fine.$
How's your training going on?$
$
7.在文件中显示制表符分隔的行
在下面的输出中,我们可以看到TAB空间被' ^ I '字符填充。
# cat -T test
hello ^Ieveryone, how do you do?
Hey, ^Iam fine.^I^IHow's your training ^Igoing on?
Let's do ^Isome practice in Linux.
8.一次显示多个文件
在下面的示例中,我们有三个文件test,test1和test2,并且能够查看这些文件的内容,如上所示。我们需要用;分隔每个文件;(半冒号)。
# cat test; cat test1; cat test2
This is test file
This is test1 file.
This is test2 file.
9.将标准输出与重定向运算符一起使用
我们可以将文件的标准输出重定向到新文件,或者使用' > '(大于)符号将其重新存在。小心,test1的现有内容将被测试文件的内容覆盖。
# cat test > test1
10.使用重定向运算符附加标准输出
在现有文件中附加' >> '(大于1的符号)。这里,测试文件的内容将附加在test1文件的末尾。
# cat test >> test1
11.使用重定向运算符重定向标准输入
当您将重定向与标准输入' < '(小于符号)一起使用时,它将文件名test2用作命令的输入,并且输出将显示在终端中。
# cat < test2
This is test2 file.
12.重定向单个文件中包含的多个文件
这将创建一个名为test3的文件,所有输出都将重定向到新创建的文件中。
# cat test test1 test2 > test3
13.在单个文件中对多个文件的内容进行排序
这将创建一个文件test4,并将cat命令的输出通过管道传递到进行排序,结果将重定向到新创建的文件中。
# cat test test1 test2 test3 | sort > test4
10,sh和bash命令
一、sh和bash命令用法:
sh filename
在当前bash环境下读取并执行filename中的命令。
该filename文件可以无"执行权限"
例如:在itzsmfgx文件中写入如下内容
#!/bin/sh
a="Hello, this is itzsmfgx"
echo $a
itzsmfgx文件无执行权限,直接在linux上执行sh itzsmfgx即可出结果,如下图所示。
二、./的命令用法:
./filename
作用:打开一个子shell来读取并执行filename中命令。
注:
运行一个shell脚本时会启动另一个命令解释器。
每个shell脚本有效地运行在父shell(parent shell)的一个子进程里。
这个父shell是指在一个控制终端或在一个xterm窗口中给你命令指示符的进程。
shell脚本也可以启动他自已的子进程.这些子shell(即子进程)使脚本并行地,有效率地地同时运行脚本内的多个子任务。
用此种方法执行脚本时,必须给脚本赋予执行权限,如果不没有执行权限则会报如下没有权限。
给脚本赋予执行权限后,再执行即可
x,echo命令
用 echo 显示字符串
其实非常的简单,就是在 echo 后面加上想要显示的内容就好了:
[roc@roclinux ~]$ echo 'Hello World' Hello World [roc@roclinux ~]$ echo "Hello World" Hello World [roc@roclinux ~]$ echo Hello World Hello World
至于单引号、双引号、不加引号的区别,还请看下面的内容。
用 echo 显示变量的值
在 echo 的后面,不仅可以加字符串,还可以加变量名:
#我们定义了一个变量, 叫作str [roc@roclinux ~]$ str="Hello World" #在echo后面加上str变量, 照样可以显示出来 [roc@roclinux ~]$ echo "$str, good morning" Hello World, good morning
神奇的反斜杠转义
转义字符,是 Shell 中的一些具有特殊功能的字符,比如 \n 表示换行、\t 表示制表符等。转义字符统一由反斜线“\”开头,后跟一个或几个字符,这样就赋予了字符“神奇的能力”。
在 echo 中,要使用转义字符,需要使用-e
选项,并使用双引号将转义字符括起来。
下面来看看实际的用法吧:
#一个很普通的Hello World [roc@roclinux ~]$ echo "Hello World" Hello World #尾部带有\n的Hello World, \n并没有被赋予"神奇的能力" [roc@roclinux ~]$ echo "Hello World\n" Hello World\n #使用了-e选项后, \n被赋予了"神奇的能力", 它实现了换行效果 [roc@roclinux ~]$ echo -e "Hello World\n" Hello World
从上面的例子可以得出结论:
- 不带
-e
选项的 echo,将 \n 认为是普通字符; - 使用了
-e
选项的 echo,会将 \n 认为是换行符。
其实世间还有很多转义字符,我们来一起开开眼界,如表 1 所示。
打印参数 | 解 释 |
---|---|
\a | 响铃 |
\b | 退格(backspace) |
\e | 转义符 |
\c | 不换行 |
\f | 换页 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ONNN | 字节数以八进制数 NNN (1 至 3 位)表不 |
\xHH | 字节数以十六进制数 HH (1 至 2 位)表不 |
关闭 echo 的自动换行行为
默认情况下,echo 会在内容输出之后换行。如果平时没有注意过的话,这里再为大家演示一遍:
[roc@roclinux ~]$ echo "Hello World" Hello World [roc@roclinux ~]$
如果希望改变这种默认的换行行为,有两种方法:
- 用
-n
选项去掉 echo 末尾的换行符; - 用
-e
选项打印出转义字符。
在开发 Shell 程序时,我们经常需要用户在一些提示语句后面的同一行输入一些内容,这时,我们就需要用到“让 echo 不换行”的技能了。
面的例子中,我们显示“Enter your username:”的同时不进行换行,等待用户在提示语后面输入他们的用户名,这种体验要比换行后输入用户名更友好:
#使用-n后, echo后面的换行效果消失了, 这也就导致了Shell提示符显示在了提示语同一行的后面 [roc@roclinux ~]$ echo -n "Enter your username:" Enter your username:[roc@roclinux ~]$ #用-e选项加\c转义符, 也可以实现不换行效果 [roc@roclinux ~]$ echo -e "Enter your username:\c" Enter your username:[roc@roclinux ~]$
echo 后面的引号
在文章开始阶段,我们为大家展示了三种 Hello World,大家还记得下面这三个命令吧:
[roc@roclinux ~]$ echo 'Hello World' Hello World [roc@roclinux ~]$ echo "Hello World" Hello World [roc@roclinux ~]$ echo Hello World Hello World
这三个 echo 命令的写法不同,但却有着相同的输出,所以很多人就误以为单引号、双引号、不加引号的效果是相同的。希望看完这一段落,大家会对这些引号拥有新的认识。
输入命令 | 输出内容 | 解 释 |
---|---|---|
echo '$USER * $(date)' | $USER * $(date) | 单引号无视所有特殊字符,所有字符在它眼里 都是普通字符,都是芸芸众生 |
echo "$USER * $(date)" | root * Thu Feb 25 12:03:48 CST 2016 | 双引号会无视文件通配符,但“$”、“\”、 会起作用,我管它们叫“美金”、“砍刀”、 “硫酸雨” |
echo $USER * $(date) | root book others Thu Feb 25 12:03:48 CST 2016 | $USER 被翻译了 root, * 被翻译了 book, others 是我当前目录下的目录结构 |
我们由表 2 可以看出,单引号将所有字符都看成普通字符,双引号会解释$
、\
和`
这三种特殊字符,不加引号的话则会解释所有特殊字符。
如果我们想用 echo 打印出双引号,该怎么做呢:
方法一:echo"\"Hello World\"",最外层是双引号,它不敢无视“砍刀”,所以\
能起到转义字符的作用,可以把后面的"
打印出来。
方法二:echo‘"Hello World"’,最外层是单引号,无视所有特殊字符包括双引号,所以双引号被认为是普通字符。
[roc@roclinux ~]$ echo "\"Hello World\"" "Hello World" [roc@roclinux ~]$ echo '"Hello World"' "Hello World"
既然有打印双引号的需求,也就有可能打印单引号,方法是类似的,使用双引号套单引号就可以实现了:
[roc@roclinux ~]$ echo "'Hello World'" 'Hello World'
这时有些 GEEK 会发出疑问了,如果单引号中间套单引号,或者双引号中间套双引号,会是什么结果呢?
[root@roclinux ~]# echo ""Hello World"" Hello World
从输出的内容可以看出,并没有任何的双引号被显示出来,这是为什么呢?
原来,在 Shell 中,一个双引号会去寻找它右边最靠近它的那个双引号进行配对,形成“一对双引号”。所以我们上面的命令事与愿违了,echo 会认为我们要打印三块内容:
- 一对双引号,内容是空的
- Hello World
- 又一对双引号,内容还是空的
在 Shell 中显示色彩
echo 命令,中文叫作“回声”,echo 还有另一面,那就是它色彩斑斓的一面。耳听为虚,眼见为实,我们先来看一个示例,如图 1 所示。
图1
看到了吧,echo 命令输出了红底青字,大家也看到了 echo 的另一面。原理其实并不难,echo 是通过使用“转义序列”来为世界涂上颜色的。语法格式如下:
echo -e "\033[颜色1;颜色2m 要展示的文字 \033[0m"
格式详解:
- -e选项:表示允许反斜杠(对字符)转义。
- \033[颜色1;颜色2m:称为转义序列,它本身是一个整体,中间不要有空格。
- \033[:转义序列的开始。其中\033代表Esc符号,也可以使用\E或\e来代替。
- 颜色1和颜色2:表示字体的前景色或背景色,至于颜色1和颜色2哪一个表示前景色,哪一个表示背景色,由其设定的数值来决定,前景色和背景色的数值空间是不同的。
- m:转义序列的终止标志。
- \033[0m:表示将颜色恢复回原来的配色。
好了,了解完原理,我们再来详细看一下上面的示例,如图 2 所示。
图2
图 2 中所有涉及的颜色如表 3 所示。
色彩 | 黑 | 红 | 绿 | 黄 | 蓝 | 洋红 | 青 | 白 |
---|---|---|---|---|---|---|---|---|
前景色 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
背景色 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
在脚本中显示色彩
脚本中使用 echo 显示色彩的方法有两种:
- 在 Shell 脚本中事先定义好“颜色变量”,然后使用 echo-e 来调用变量显示颜色。
- 在 Shell 脚本中事先定义好“颜色动作”,然后直接调用动作来输出变量。
我们通过两个示例来为大家展示什么是颜色变量,什么又是颜色动作。
第一种方法:定义颜色变量
#!/bin/bash # 定义颜色变量, 还记得吧, \033、\e和\E是等价的 RED='\E[1;31m' # 红 GREEN='\E[1;32m' # 绿 YELOW='\E[1;33m' # 黄 BLUE='\E[1;34m' # 蓝 PINK='\E[1;35m' # 粉红 RES='\E[0m' # 清除颜色 # 真正使用时, 我们通过echo -e来调用 echo -e "${RED}Red color${RES}" echo -e "${YELOW}Yelow color${RES}" echo -e "${BLUE}Blue color${RES}" echo -e "${GREEN}Green color${RES}" echo -e "${PINK}Pink color${RES}"
这种方法的原理是,把转义序列定义为变量,echo 时直接引用变量就行了。
第二种方法:定义颜色动作
#!/bin/bash # 定义颜色动作, 把echo -e也定义到变量中 SETCOLOR_SUCCESS="echo -en \\E[1;32m" SETCOLOR_FAILURE="echo -en \\E[1;31m" SETCOLOR_WARNING="echo -en \\E[1;33m" SETCOLOR_NORMAL="echo -en \\E[0;39m" # 使用时直接调用颜色动作即可 $SETCOLOR_SUCCESS && echo SUCCESS $SETCOLOR_FAILURE && echo FAILURE $SETCOLOR_WARNING && echo WARNING $SETCOLOR_NORMAL && echo NORMAL
第二种方法和第一种方法的思路类似,唯一不同的是我们把 echo 也加入到了定义中。这样有一个好处就是,使用时不用频繁输入 echo 了。不过,需要注意其中的一些细节:
- 需要增加
-n
选项,这样引用时不会出现换行的问题。 \\
本质是\
,在双引号中反斜线符号一定要写成\\
。- 引用变量要放到其他语句前面,并使用
&&
连接。
好了,有了这些知识,相信你一定能让你的 Shell 程序绚烂多彩的,给用户带来一次视觉上的饕餮大餐。
拥抱 terminfo,逃避火星文
截至目前,我们所掌握的两种“涂色”方法,都是通过转义序列来实现的。使用转义序列会有一个很不爽的地方,那就是我们要记忆“反人类的”火星文(\E[1;31m),这无论对谁来说,都会是一个负担。那么,有没有比较优雅的方式来实现“涂色”呢?
有的,要相信世界是美好的。我们可以通过 terminfo 来实现。那么,terminfo 是什么呢?
UNIX 诞生之初,计算机专家们就是利用终端来登录到 UNIX 主机的,而不同类型的终端使用着不同的命令集,这会导致终端与 UNIX 之间无法配合工作。
为了解决这个问题,计算机专家们将几乎所有类型的终端的命令集都存储到了一个数据库中,以便实现统一化、标准化的处理和响应。而这个数据库就被称为 terminfo。
要想逃避火星文,我们需要 terminfo 的帮忙,而 tput 便是帮我们与 terminfo 建立联系的那个人。
tput 让我们简单地涂色
tput 命令会利用 terminfo 数据库中的信息,来控制和更改我们的终端,比如控制光标、更改文本属性、控制屏幕,以及为文本涂色。
其中,为文本涂色的方法是:
- tput setab:用于设置背景色;
- tput setaf:用于设置前景色。
其中颜色的定义如表 4 所示。
数值 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
颜色 | 黑色 | 红色 | 绿色 | 黄色 | 蓝色 | 洋红色 | 黄色 | 白色 |
好了,万事俱备,只欠东风,我们来通过 tput 编写涂色脚本吧:
RED=$(tput setaf 1) GREEN=$(tput setaf 2) RESET=$(tput sgr0) echo "${RED}red text ${GREEN}green text${RESET}"
这样看着清爽直观多了,解答一个可能的疑惑:sgr0 表示颜色重置。