Shell脚本学习(上)
第一个shell脚本
打开文本编辑器(可以使用 vi/vim 命令来创建文件),新建一个文件 test.sh,扩展名为 sh(sh代表shell),如果你用 php 写 shell 脚本,扩展名就用 php 好了。
输入一些代码,第一行一般是这样:
#!/bin/bash
echo "Hello World !"
#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。
运行 Shell 脚本有两种方法
1、作为可执行程序
将上面的代码保存为 test.sh,并 cd 到相应目录:
$ chmod +x ./test.sh #使脚本具有执行权限
$ ./test.sh #执行脚本
注意,一定要写成 ./test.sh,而不是 test.sh,运行其它二进制的程序也一样,直接写 test.sh,linux 系统会去 PATH 里寻找有没有叫 test.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找。
2、作为解释器参数
这种运行方式是,直接运行解释器,其参数就是 shell 脚本的文件名,如:
$ /bin/sh test.sh
这种方式运行的脚本,不需要在第一行指定解释器信息。
Shell变量
定义变量时,变量名不添加 $ 符号
Url="www.baidu.com"
注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
- 中间不能有空格,可以使用下划线(_)。
- 不能使用标点符号。
- 不能使用bash里的关键字(可用help命令查看保留关键字)。
使用变量时,只需要在变量名前添加 $ 符号即可
Url="www.baidu.com"
echo $Url
echo ${Url}
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:
echo "${Url} is a great Search Engines"
推荐给所有变量加上花括号,这是个好的编程习惯。
已定义的变量,可以被重新定义,如:
#!/bin/bash
Url="baidu"
echo $Url
Url="google"
echo $Url
只读变量
使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。
下面的例子尝试更改只读变量,结果报错:
#!/bin/bash
Url="https://www.baidu.com"
readonly Url
Url="https://www.google.com"
运行脚本,结果如下:
./test.sh: 行 5: Url:只读变量
删除变量
使用 unset 命令可以删除变量。
#!/bin/sh
Url="https://www.baidu.com"
unset Url
echo $Url
变量被删除后不能再次使用。unset 命令不能删除只读变量。以上实例执行将没有任何输出。
变量类型
运行shell时,会同时存在三种变量:
- 1) 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
- 2) 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
- 3) shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
传递参数
我们可以在执行 Shell 脚本时,向脚本传递参数。
传递方式为 ./test.sh param1 param2 ...
在shell文件中接收参数
#!bin/bash
echo "参数个数:$#"
echo "第0个参数:执行的文件名 $0";
echo "第一个参数:$1";
...
echo "传递的参数作为一个字符串显示:$*";
echo "传递的参数作为一个字符串数组显示:$@";
数组
数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小。与大部分编程语言类似,数组元素的下标由 0 开始。
Shell 数组用括号来表示,元素用 空格 符号分割开。
#!bin/bash
#全部初始化
array=(value0 value1 ... valuen)
#逐个初始化
array[0]=value0;
array[0]=value1;
...
#获取指定元素
echo "第n个元素:${array[n]}"
#使用@ 或 * 可以获取数组中的所有元素
echo "数组的元素为: ${array[*]}"
echo "数组的元素为: ${array[@]}"
#获取数组长度
echo "数组元素个数为: ${#array[*]}"
echo "数组元素个数为: ${#array[@]}"
基本运算符
Shell 和其他编程语言一样,支持多种运算符,包括:
- 算数运算符
- 关系运算符
- 布尔运算符
- 字符串运算符
算数运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,expr
最常用。
expr
是一款表达式计算工具,使用它能完成表达式的求值操作。
注意使用的是反引号 ` 而不是单引号 ’
也可以用$[a+b]
这类算数运算
#!/bin/bash
val=`expr 2 + 2`
val=$[a+b]
echo "两数之和为 : $val"
result=`expr $a - $b`
result=$[a-b]
result=`expr $a \* $b`
result=$[a*b]
result=`expr $b / $a`
result=$[a/b]
result=`expr $b % $a`
result=$[a%b]
#!赋值
a=$b
[ $a == $b ]
[ $a != $b ]
条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。
注意:
- 乘号()前边必须加反斜杠()才能实现乘法运算;
- 在 MAC 中 shell 的 expr 语法是:$((表达式)),此处表达式中的 "" 不需要转义符号 “” 。
- 使用 $[a*b]
不需要转义字符
关系运算符
a=10;b=20;
运算符 | 说明 | 举例 | |
---|---|---|---|
-eq | equal | 检测两个数是否相等,相等返回 true。 | [ $a -eq $b ] 返回false。 |
-ne | not_equal | 检测两个数是否不相等,不相等返回 true。 | [ $a -ne $b ] 返回 true。 |
-gt | greater_than | 检测左边的数是否大于右边的,如果是,则返回 true。 | [ $a -gt $b ] 返回 false。 |
-lt | less_than | 检测左边的数是否小于右边的,如果是,则返回 true。 | [ $a -lt $b ] 返回 true。 |
-ge | greater_equal | 检测左边的数是否大于等于右边的,如果是,则返回 true。 | [ $a -ge $b ] 返回 false。 |
-le | lesse_qual | 检测左边的数是否小于等于右边的,如果是,则返回 true。 | [ $a -le $b ] 返回 true。 |
布尔运算符
运算符 | 说明 | 举例 | |
---|---|---|---|
! | 非运算,表达式为 true 则返回 false,否则返回 true。 | [ ! false ] 返回 true。 | |
-o | or | 或运算,有一个表达式为 true 则返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a | and | 与运算,两个表达式都为 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
逻辑运算符
运算符 | 说明 | 举例 |
---|---|---|
&& | 逻辑的 AND | [[ $a -lt 100 && $b -gt 100 ]] 返回 false |
|| | 逻辑的 OR | [[ $a -lt 100 || $b -gt 100 ]] 返回 true |
字符串运算符
下表列出了常用的字符串运算符,假定变量 a 为 “abc”,变量 b 为 “efg”:
运算符 | 说明 | 举例 |
---|---|---|
= ==也行 | 检测两个字符串是否相等,相等返回 true。 | [ $a = $b ] 返回 false。 |
!= | 检测两个字符串是否不相等,不相等返回 true。 | [ $a != $b ] 返回 true。 |
-z | 检测字符串长度是否为0,为0返回 true。 | [ -z $a ] 返回 false。 |
-n | 检测字符串长度是否不为 0,不为 0 返回 true。 | [ -n “$a” ] 返回 true。 |
$ | 检测字符串是否为空,不为空返回 true。 | [ $a ] 返回 true。 |
echo打印输出
1.显示普通字符串:
echo "It is a test"
这里的双引号完全可以省略,以下命令与上面实例效果一致:
echo It is a test
2.显示转义字符
echo "\"It is a test\""
结果将是:
"It is a test"
3.显示变量
read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量
name="$1"
echo "$name It is a test"
以上代码保存为 test.sh,name 接收标准输入的变量,结果将是:
./test.sh OK
OK It is a test #输出
4.显示换行
echo -e "OK! \n" # -e 开启转义 \n 换行
echo "It is a test"
输出结果:
OK!
It is a test
5.显示不换行
echo -e "OK! \c" # -e 开启转义 \c 不换行
echo "It is a test"
输出结果:
OK! It is a test
6.显示结果定向至文件
echo "It is a test" > myfile
7.原样输出字符串,不进行转义或取变量(用单引号)
echo '$name\"'
输出结果:
$name\"
8.显示命令执行结果
echo $(date)
echo `date`
注意: 这里使用的是反引号 `, 而不是单引号 '。
建议使用 $()
该方式支持嵌套
结果将显示当前日期
2021年 08月 05日 星期四 14:53:35 CST
2021年 08月 05日 星期四 14:53:35 CST
9.显示带有颜色的字符串
字体状态:高亮加粗=1,下划线=4,闪烁=5;
字体颜色:黑色=30,红色=31,绿色=32,黄色=33,蓝色=34,紫色=35,青色=36,白色=37;
背景色 黑色=40,红色=41,绿色=42,黄色=43,蓝色=44,紫色=45,青色=46,白色=47;
echo -e "\e[字体状态;字背景颜色;文字颜色m ${str} \e[0m"
\e[0m
将字体重新置回。
将输出的字体状态设置为闪烁:
echo -e "\e[5m This is red text! \e[0m"
将输出的文本背景色设置为蓝底:
echo -e "\e[44m This is red text! \e[0m"
将输出的字体色设置为红色:
echo -e "\e[31m This is red text! \e[0m"
将输出的文本设置为红底黄字:
echo -e "\e[41;33m This is red text! \e[0m"
闪烁 红底 黄字 :
echo -e "\e[5;41;33m This is red text! \e[0m"
printf打印输出
printf
命令模仿 C 程序库(library)里的 printf()
程序。
printf
由 POSIX 标准所定义,因此使用 printf 的脚本比使用 echo
移植性好。
printf
使用引用文本或空格分隔的参数,可以在 printf
中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认的 printf
不会像 echo
自动添加换行符,我们可以手动添加 \n
。
#!/bin/bash
printf "%-10s %-8s %-4s %-8s %-8s\n" 姓名 性别 语文成绩 数学成绩 英语成绩
printf "%-10s %-8s %-8.1f %-8.1f %-8.1f\n" 张三 男 76.5 86 61
printf "%-10s %-8s %-8.1f %-8.1f %-8.1f\n" 李四 女 68 100 30.5
printf "%-10s %-8s %-8.1f %-8.1f %-8.1f\n" 王五 男 87 55.5 88
姓名 性别 语文成绩 数学成绩 英语成绩
张三 男 76.5 86.0 61.0
李四 女 68.0 100.0 30.5
王五 男 87.0 55.5 88.0
%s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实数,以小数形式输出。
%-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
%-4.2f 指格式化为小数,其中 .2 指保留2位小数。
printf 的转义序列
序列 | 说明 |
---|---|
\a | 警告字符,通常为ASCII的BEL字符 |
\b | 后退 |
\c | 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略 |
\f | 换页(formfeed) |
\n | 换行 |
\r | 回车(Carriage return) |
\t | 水平制表符 |
\v | 垂直制表符 |
\ | 一个字面上的反斜杠字符 |
\ddd | 表示1到3位数八进制值的字符。仅在格式字符串中有效 |
\0ddd | 表示1到3位的八进制值字符 |