概述
终端打印
玩转变量与环境变量
使用函数填加环境变量
通过shell进行数学运算
玩转文件描述符与重定向
数组和关联数组
使用别名
获取终端信息
获取、设置日期及延时
调试脚本
函数和参数
将命令序列的输出读入变量
以不按回车键的方式获取字符”n”
运行命令直至执行成功
字段分隔符和迭代器
比较与测试
简介
本系列博客使用的是Bash(Bourne Again Shell),它是目前大多数GNU/Linux系统默认的shell环境。
查看默认的shell
[root@entel2 ~]# echo $SHELL /bin/bash [root@entel2 ~]# echo $0 -bash [root@entel2 ~]# env |grep SHELL SHELL=/bin/bash
$和#
提示符
打开终端后,就会出现一个提示符。其形式通常如下:
username@hostname$
或者
root@hostname #
要么就简单地以$或#表示, 格式其实是有 PS1(“prompt string one” 的简写)决定的, 这里我们要说的是 # 和 $
$表示普通用户, #表示管理员用户root
[root@entel2 ~]#
oracle@entel2:[/oracle]$
root是Linux系统中权限最高的用户。
注:
以root用户(管理员)的身份直接使用shell来执行任务可不是个好主意。因为如果shell具备较高的权限,命令中出现的输入错误有可能造成更严重的坏。
所以推荐使用普通用户登录系统(使用$来表明这种身份,root登录时要使用#), 然后借助sudo这类工具来运行特权命令。
使用sudo <command> <arguments>这种形式执行命令的效果和root一样。
shell脚本通常是一个以shebang起始的文本文件
shebang这个词其实是两个字符名称的组合。
在Unix的行话里,用sharp或hash(有时候是mesh)来称呼字符“ #”,用bang来称呼惊叹号“ !”,因而shebang合起来就代表了这两个字符。
#!/bin/bash
shebang是一个文本行,其中#!位于解释器路径之前。 /bin/bash是Bash的解释器命令路径。
运行脚本的两种方式
将脚本作为bash的命令行参数
将脚本作为命令行参数时的运行方式如下(#号后面的文本是注释,不必输入到命令行中):
$ bash script.sh #假设脚本位于当前目录下
或者
$ bash /home/path/script.sh #使用script.sh的完整路径
如果将脚本作为bash的命令行参数来运行,那么就用不着脚本中的shebang了。
授予脚本执行权限,将其变为可执行文件
要是有需要的话,可以利用shebang来实现脚本的独立运行。对此必须设置脚本的可执行权限,这样它就可以使用位于#!之后的解释器路径来运行了。
就像这样:
$ chmod a+x script.sh
该命令赋予所有用户script.sh文件的可执行权限。这个脚本能以下列方式执行:
$ ./script.sh #./表示当前目录
或者
$ /home/path/script.sh #使用脚本的完整路径
内核会读取脚本的首行并注意到shebang为#!/bin/bash。它识别出/bin/bash并在内部像这样执行该脚本:
$ /bin/bash script.sh
当启动shell时,它一开始会执行一组命令来定义诸如提示文本、颜色等各类设置。这组命令来自位于用户主目录中的脚本文件~/.bashrc(对于登录shell则是~/.bash_profile)。
Bash还维护了一个历史记录文件~/.bash_history,用于保存用户运行过的命令。
~表示主目录,它通常是/home/user,其中user是用户名,如果是root用户则为/root。
在Bash中,每个命令或是命令序列是通过使用分号或换行符来分隔的。比如:
$ cmd1 ; cmd2
它等同于:
$ cmd1 $ cmd2
如果 是 cmd1&&cmd2 只有当cmd1执行成功才回执行cmd2,而 ; 则没有这个限制。
字符#指明注释的开始。
注释部分以#为起始,一直延续到行尾。注释行通常用于为代码提供注释信息,或者停止执行某行代码。(shell不执行脚本中的任何注释部分。)
终端打印
终端是交互式工具,用户可以通过它与shell环境进行交互。
在终端中打印文本是绝大多数shell脚本和工具日常需要执行的基本任务。在这则攻略中我们会看到, 可以使用各种方法,采用各种格式进行打印.
echo
之前整理了一篇 Shell echo-使用echo实现更复杂的输出格式控制
这里再此说明一下:
echo是用于终端打印的基本命令。
在默认情况下,echo在每次调用后会添加一个换行符。
[root@entel1 ~]# echo "welcome to the blog of Bash" welcome to the blog of Bash
只需要使用带双引号的文本,结合echo命令就可以将该文本在终端中打印出来。
类似地,不带双引号的文本也可以得到同样的输出结果:
[root@entel1 ~]# echo welcome to the blog of Bash welcome to the blog of Bash
当然了,使用单引号同样也可以达到相同的目的
[root@entel1 ~]# echo 'welcome to the blog of Bash' welcome to the blog of Bash
这些方法看起来相似,但各有一些特殊用途和副作用,看如下命令。
[root@entel1 ~]# echo "hello world !" -bash: !": event not found [root@entel1 ~]# echo "!" -bash: !: event not found
命令将会返回:
bash: !: event not found error
因此,如果需要打印!,那就不要将其放入双引号中,或者你可以在其之前加上个特殊的转义字符(\)将!转义,就像这样:
[root@entel1 ~]# echo hello world ! hello world ! [root@entel1 ~]# echo 'hello world!' hello world! [root@entel1 ~]# echo "hello world \!" #将转义字符放在前面 hello world \!
每种方法的副作用:
- 使用不带引号的echo时,没法在所要显示的文本中使用分号(;),因为分号在Bash shell 中被用作命令定界符。
如下:
[root@entel1 ~]# echo ; [root@entel1 ~]# echo linux shell ; linux shell
- 以echo hello;hello为例, echo hello被视为一个命令,第二个hello则被视为另一 个命令。
[root@entel1 ~]# echo ls ; ls ls anaconda-ks.cfg Desktop Downloads install.log.syslog Music Pictures Templates
变量替换在单引号中无效
使用单引号时,变量不会被扩展(expand),将依照原样显示。这意味着:
$ echo '$var' will print $var
但如果变量var已经定义过,那么$ echo "$var"
会打印出该变量的值;
如果没有定义过,则什么都不打印。
[root@entel1 Templates]# cat test.sh #!/bin/bash var=xiaogongjiang echo '$var' will print $var echo '$var2' will print $var2 [root@entel1 Templates]# ./test.sh --观察var2的输出为空,因为未定义 $var will print xiaogongjiang $var2 will print [root@entel1 Templates]#
printf
之前整理了一篇 Shell printf 命令
这里再此说明一下:
printf使用的参数和C语言中的printf函数一样。
[root@entel1 ~]# printf "hello world" hello world[root@entel1 ~]#
printf使用引用文本或由空格分隔的参数。
我们可以在printf中使用格式化字符串,还可以指定字符串的宽度、左右对齐方式等。
在默认情况下, printf并不像echo命令一样会自动添加换行符,我们必须在需要的时候手动添加,比如在下面的脚本中:
[root@entel1 ~]# cat print.sh #!/bin/bash #文件名:print.sh printf "%-5s %-10s %-4s\n" No Name Mark printf "%-5s %-10s %-4.2f\n" 1 Sarath 80.3456 printf "%-5s %-10s %-4.2f\n" 2 James 90.9989 printf "%-5s %-10s %-4.2f\n" 3 Jeff 77.564 [root@entel1 ~]# chmod +x print.sh [root@entel1 ~]# ./print.sh No Name Mark 1 Sarath 80.35 2 James 91.00 3 Jeff 77.56
注释:
%s、 %c、 %d和%f都是格式替换符(format substitution character),其所对应的参数可以置于带引号的格式字符串之后。
%-5s指明了一个格式为左对齐且宽度为5的字符串替换(-表示左对齐)。如果不用-指定对齐方式,字符串就采用右对齐形式。
宽度指定了保留给某个变量的字符数。对Name而言,保留宽度是10。因此,任何Name字段的内容都会被显示在10字符宽的保留区域内,如果内容不足10个字符,余下的则以空格符填充。
对于浮点数,可以使用其他参数对小数部分进行舍入。
对于Mark字段,将其格式化为%-4.2f,其中.2指定保留2个小数位。
注意,在每行格式字符串后都有一个换行符(\n)
其他注意事项
使用echo和printf的命令选项时,要确保选项应该出现在命令行内所有字符串之前,否则Bash会将其视为另外一个字符串。
在echo中转义换行符
在默认情况下, echo会将一个换行符追加到输出文本的尾部。可以使用选项-n来忽略结尾的换行符。
echo同样接受双引号字符串内的转义序列作为参数。如果需要使用转义序列,则采用echo –e “包含转义序列的字符串”这种形式。例如:
注意比较
[root@entel1 ~]# echo -e "1\t2\t3" 1 2 3 [root@entel1 ~]# echo -e "a\tb\tc" a b c [root@entel1 ~]# echo "a\tb\t\c" a\tb\t\c
打印彩色输出
在终端中生成彩色输出相当好玩,我们可以使用转义序列来实现。
每种颜色都有对应的颜色码。比如:重置=0,黑色=30,红色=31,绿色=32,黄色=33,蓝色=34,洋红=35,青色=36,白色=37。
要打印彩色文本,可输入如下命令:
echo -e "\e[1;31m This is red text \e[0m"
\e[1;31将颜色设为红色,\e[0m将颜色重新置回。
只需要将31替换成想要的颜色码就可以了。
要设置彩色背景,经常使用的颜色码是:重置=0,黑色=40,红色=41,绿色=42,黄色=43,蓝色=44,洋红=45,青色=46,白色=47。
要打印彩色文本,可输入如下命令:
echo -e "\e[1;42m Green Background \e[0m"