shell 使用总结
1.默认目录
凡是自定义的脚本建议放在/usr/local/sbin/目录下、容易归档而且接管的管理员容易知道自定义脚本放哪。
2.后缀
shell脚本通常以.sh作为后缀。
3.首行
test.sh中第一行一定是 “#! /bin/bash” 它代表的意思是,该文件使用的是bash语法。
#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。
echo 命令用于向窗口输出文本。
4.注释
4.1 单行注释
’#’表示注释,在前面讲过的。后面跟一些该脚本的相关注释内容以及作者和创建日期或者版本等等。
例子:
# This shell script is about xxxx.
# Writen by Allen 2019-09-16.
4.2 多行注释
格式:
:<<EOF
注释内容…
注释内容…
注释内容…
EOF
EOF 也可以使用其他符号:
:<<’
注释内容…
注释内容…
注释内容…
’
:<<!
注释内容…
注释内容…
注释内容…
!
5.执行shell命令
(例子:脚本 test.sh )
vim编写的文档不具有执行权限,加个权限后可以直接使用./filename来执行。
chomd +x test.sh
./test.sh
直接使用sh命令去执行脚本。
sh test.sh
添加-x 查看脚本执行过程。
sh -x test.sh
6.变量
6.1 目的
使用变量便于修改,避免批量替换。
6.2 使用变量
在脚本中引用变量要加上‘$’符号。
echo $your_name
echo ${your_name}
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:
for skill in Ada Coffe Action Java; do
echo “I am good at ${skill}Script”
done
如果不给skill变量加花括号,写成echo “I am good at $skillScript”,解释器就会把$skillScript当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。
推荐给所有变量加上花括号,这是个好的编程习惯。
6.3 数学计算要用’[ ]’括起来并且外头要带一个’$’。
6.4 ”read x”表示x变量的值需要用户通过键盘输入得到。
6.5 read -p
echo “Please input a number:”
read x
相当于
read -p "Please input a number: " x
输出:
Please input a number:
6
Please input a number: 6
6.6 传递参数
shell脚本在执行后面可以跟预设变量。
$0 为脚本本身名字。
$1 $2 代表执行命令后缀预设变量第几个。
$# 传递到脚本的参数个数。
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
$* 以一个单字符串显示所有向脚本传递的参数。
$@ 与$*相同,但是使用时加引号,并在引号中返回每个参数。
$* 与 $@ 区别:
- 相同点:都是引用所有参数。
- 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 “1 2 3”(传递了一个参数),而 “@” 等价于 “1” “2” “3”(传递了三个参数)。
6.7 只读变量
使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变
readonly variable_name
6.8 删除变量
使用 unset 命令可以删除变量。语法:
unset variable_name
变量被删除后不能再次使用。unset 命令不能删除只读变量。
6.9 变量类型
运行shell时,会同时存在三种变量:
- 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
- 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
- shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
7.逻辑判断
7.1 不带else
if 判断语句; then
command
fi
判断语句使用两个括号,例如:((a<60))。
7.2 带有else
if 判断语句; then
command
else
command
fi
7.3 带有elif
if 判断语句一;then
command
elif 判断语句二;then
command
else
command
fi
7.4 case
case 变量 in
value1)
command
;;
value2)
command
;;
value3)
command
;;
*)
command
;;
esac
8.循环
8.1 for 循环
格式
for 变量名 in 循环条件 ;do
command
done
例子
for i in `seq 1 5`;do
echo $i
done
输出
1
2
3
4
5
8.2 while 循环
格式
while 条件; do
command
done
例子
a=5
while [ $a -ge 1 ]; do
echo “$a”
a=$[ $a - 1 ]
done
输出
5
4
3
2
1
8.3 until 循环
until 语法格式:
until condition
do
command
done
8.4 break命令
break命令允许跳出所有循环(终止执行后面的所有循环)。
8.5 continue 命令
continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。
9.函数
9.1 格式
function 函数名() {
command
[return int;]
}
说明:
1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255
函数返回值在调用该函数后通过 $? 来获得。
例子
function sum() {
sum=$[ $1 + $2 ]
echo $sum
}sum $1 $2
输出
sh test.sh 5 6
11
9.2 函数位置
在shell脚本中,函数一定要写在最前面,不能出现在中间或者最后,因为函数是要被调用的,如果还没有出现就被调用,肯定是会出错的。
10.字符串
10.1 单引号
单引号字符串的限制:
- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
- 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
10.2 双引号
双引号的优点:
- 双引号里可以有变量
- 双引号里可以出现转义字符
10.3 拼接字符串
例子
your_name=“runoob”
# 使用双引号拼接
greeting=“hello, “$your_name” !”
greeting_1=“hello, ${your_name} !”
echo $greeting $greeting_1
# 使用单引号拼接
greeting_2=‘hello, ‘$your_name’ !’
greeting_3=‘hello, ${your_name} !’
echo $greeting_2 $greeting_3
10.4 获取字符串长度
a=“abcd”
echo ${#a} #输出4
10.5 提取子字符串
以下实例从字符串第 2 个字符开始截取 4 个字符:
string=“runoob is a great site”
echo ${string:1:4} # 输出 unoo
10.6 查找子字符串
查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):
string=“runoob is a great site”
echo `expr index “$string” io` # 输出 4
11.数组
11.1 定义数组
数组名=(值1 值2 … 值n)
11.2 读取数组
${数组名[下标]}
使用@ 或 * 可以获取数组中的所有元素,例如:
echo ${array_name[@]}
11.3 获取数组的长度
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}
12.基本运算符
12.1 算数运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
val=`expr $a \* $b`
echo “a * b : $val”
# 乘号(*)前边必须加反斜杠(\)才能实现乘法运算;
12.2 关系运算符
判断数值大小可以用”(( ))“外,还可以使用”[ ]“.
不能使用>,<,=,使用 -lt(小于), -gt(大于),-le(小于等于),-ge(大于等于),-eq(等于),-ne(不等于)。
12.3 布尔运算符
运算符 | 说明 | 举例 |
---|---|---|
! | 非运算,表达式为 true 则返回 false,否则返回 true。 | [ ! false ] 返回 true。 |
-o | 或运算,有一个表达式为 true 则返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a | 与运算,两个表达式都为 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
12.4 逻辑运算符
运算符 | 说明 | 举例 |
---|---|---|
&& | 逻辑的 AND | [[ $a -lt 100 && $b -gt 100 ]] 返回 false |
|| | 逻辑的 OR | [[ $a -lt 100 || $b -gt 100 ]] 返回 true |
12.5 字符串运算符
运算符 | 说明 | 举例 |
---|---|---|
= | 检测两个字符串是否相等,相等返回 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。 |
12.6 文本测试运算符
操作符 | 说明 |
---|---|
-b file | 检测文件是否是块设备文件,如果是,则返回 true。 |
-c file | 检测文件是否是字符设备文件,如果是,则返回 true。 |
-d file | 检测文件是否是目录,如果是,则返回 true。 |
-f file | 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 |
-g file | 检测文件是否设置了 SGID 位,如果是,则返回 true。 |
-k file | 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 |
-p file | 检测文件是否是有名管道,如果是,则返回 true。 |
-u file | 检测文件是否设置了 SUID 位,如果是,则返回 true。 |
-r file | 检测文件是否可读,如果是,则返回 true。 |
-w file | 检测文件是否可写,如果是,则返回 true。 |
-x file | 检测文件是否可执行,如果是,则返回 true。 |
-s file | 检测文件是否为空(文件大小是否大于0),不为空返回 true。 |
-e file | 检测文件(包括目录)是否存在,如果是,则返回 true。 |
13.printf 命令
13.1 语法
printf 命令的语法:
printf format-string [arguments…]
参数说明:
format-string: 为格式控制字符串
arguments: 为参数列表。
13.2 转义序列
序列 | 说明 |
---|---|
\a | 警告字符,通常为ASCII的BEL字符 |
\b | 后退 |
\c | 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略 |
\f | 换页(formfeed) |
\n | 换行 |
\r | 回车(Carriage return) |
\t | 水平制表符 |
\v | 垂直制表符 |
\\ | 一个字面上的反斜杠字符 |
\ddd | 表示1到3位数八进制值的字符。仅在格式字符串中有效 |
\0ddd | 表示1到3位的八进制值字符 |
13.3 例子
>#!/bin/bash
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876
输出
姓名 性别 体重kg
郭靖 男 66.12
杨过 男 48.65
郭芙 女 47.99
%s %c %d %f都是格式替代符
%-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
%-4.2f 指格式化为小数,其中.2指保留2位小数。
14.输入输出重定向
14.1 重定向命令列表
命令 | 说明 |
---|---|
command > file | 将输出重定向到 file。 |
command < file | 将输入重定向到 file。 |
command >> file | 将输出以追加的方式重定向到 file。 |
n > file | 将文件描述符为 n 的文件重定向到 file。 |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m | 将输出文件 m 和 n 合并。 |
n <& m | 将输入文件 m 和 n 合并。 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
14.2 深入讲解
一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:
- 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
- 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
- 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
具体使用
默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
如果希望 stderr 重定向到 file,可以这样写:
$ command 2 > file
# 2 表示标准错误文件(stderr)。
如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:
$ command > file 2>&1
如果希望对 stdin 和 stdout 都重定向,可以这样写:
$ command < file1 >file2
command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。
14.3 Here Document
Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。
它的基本的形式如下:
command << delimiter
document
delimiter
它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。
注意:
- 结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
- 开始的delimiter前后的空格会被忽略掉。
14.4 /dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
$ command > /dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
如果希望屏蔽 stdout 和 stderr,可以这样写:
$ command > /dev/null 2>&1
注意:0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
15. 文件包含
和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。
Shell 文件包含的语法格式如下:
. filename # 注意点号(.)和文件名中间有一空格
或
source filename
实例
创建两个 shell 脚本文件。
test1.sh 代码如下:
#!/bin/bash
url=“http://www.baidu.com”
test2.sh 代码如下:
#!/bin/bash
# 使用 . 号来引用test1.sh 文件
. ./test1.sh
# 或者使用以下包含文件代码
# source ./test1.sh
echo “地址:$url”
接下来,我们为 test2.sh 添加可执行权限并执行:
$ chmod +x test2.sh
$ ./test2.sh
地址:http://www.baidu.com
注:被包含的文件 test1.sh 不需要可执行权限。