参考《Linux 命令行与shell脚本编程大全》
1. 构建基本脚本
将多个shell命令放到shell脚本文件中。
1.1 shell脚本文件
第一步:创建文件
vim test
第二步:写shell脚本
#!/bin/bash
# this is a comment!
date
who
#...
第三步:赋予执行文件权限
$ chmod u+x test
第四步:运行脚本
$ ./test
1.2 基本命令
命令 | 作用 | 规则 | 示例 |
---|---|---|---|
echo | 显示消息 | 单引号或双引号将文本字符串圈起来 | echo "hello world !" |
$variable | 使用变量(环境变量、用户变量) | 变量、等号、值之间不能出现空格,shell脚本自动决定变量类型 | name="peter" echo $name |
反引号(`) | 将shell命令的输出赋给变量 | testing=`date` | |
> >> < << | 重定向输入输出 | ||
管道(|) | 将一个命令的输出重定向到另一个 | command1 | command2 在第一个命令产生输出的同时,输出会被立即送给第二个命令,传输数据不会用到任何中间文件或缓冲区。 | |
expr命令 | 允许在命令行上处理数学表达式 | $ expr 1+5 $ 6 | |
方括号($[ ]) | 数学运算 | $[operatrion] | var=$[1+5] |
bash计算器bc | 允许浮点表达式运算 | 内建,bc 开始,quit 退出 | |
exit命令 | 退出脚本 | 返回退出状态码,linux提供$? 专属变量保存上个执行命令的退出状态码 | exit 0 |
2. 使用结构化命令(条件)
2.1 if-then语句
if语句先运行if行定义的那个命令,如果该命令的退出状态码是0(表示命令运行成功),then部分的命令就会被执行,否则不执行。格式如下:
if command
then
commands
fi
2.2 if-then-else命令
if command
then
commands
else
commands
fi
2.3 嵌套if
if command
then
commands
elif command
then
commands
fi
2.2 test命令
如果test命令中列出的条件成立,test就会退出并且返回退出状态码0;如果条件不成立,返回1。
test conditon
和if-then语句配合使用
if test conditon
then
commands
fi
bash shell 提供另外一种在if-then语句中声明test命令的方法:
if [condition]
then
commands
fi
test命令可以判断3类条件:
1. 数值比较
2. 字符串比较
3. 文件比较
2.3 复合条件测试
两种布尔运算符
1. AND: [condition1] && [condition2]
2. OR: `[condition1] || [conditon2]
2.4 case命令
case命令为变量每隔可能的值指定不同的选项。
case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default_commands;;
esac
3. 更多的结构化命令(循环)
循环命令:for/while/until
3.1 for
基本格式:
#list 可以是①直接写出的列表②变量③从命令读取值(需要反引号) `cat $file`
for var in list
do
commands
done
$var 变量保持了它的值,允许我们修改它的值,并在for命令循环之外跟其他变量一样使用。
3.2 更改字段分隔符
内部字段分隔符 IFS(internal field separator, 一个特殊的环境变量),IFS定义了bash shell 用作字段分隔符的一系列字符:空格、制表符、换行符。
例如,输出文件中的每行
IFS=$'\n'
for line in `cat file.txt`
do
echo $line
done
3.3 用通配符读取目录下的文件
输出当前目录下的所有文件:
bash> echo ./*
shell脚本:
#!/bin/bash
#print file in dir
#也可以列出一系列的目录通配符
#for file in ./* /Home/Documents/*
for file in ./*
do
if [ -d "$file" ]
then
echo "$file is a directory"
elif [ -f "$file" ]
then
echo "$file is a file"
fi
done
exit 0
3.4 C语言风格的for命令
格式:
for (( variable1 assignment, variable2 assignment; conditon; iteration process ))
do
commands
done
例如1+2+3+…+10
sum=0
for (( i=1;i<=10;i++))
do
sum=$[$sum+$i]
done
echo $sum
#结果输出55
3.4 while命令
格式:
while test command
do
commands
done
3.5 until命令
和while命令完全相反
格式:
until test command
do
commands
done
3.6 控制循环
- break命令
- continue命令
3.7 重定向循环的输出
格式
for var in list
do
commands
done > output.txt
4. 处理用户输入
4.1 命令行参数
位置参数:特殊变量,分配给命令行输入的所有参数:$0是脚本的整个路径,使用
basename $0
来获取程序名,$1是第一个参数,$2直到第9个参数$9, 如果多于9个命令行参数,则在数字周围加花括号,${10}, ${11}…
basename命令:输入完整路径,返回程序名。例如:
$ basename /home/documents/test.txt
test.txt
测试参数:当脚本以为参数变量中会有数据,而实际并没有时,脚本会得到一个错误消息。在使用数据前检查数据确实已经存在于变量中。
#!/bin/bash
#cmd parameter
echo $0
name=`basename $0`
echo $name
if [ -n "$1" ]
then
echo $1
fi
exit 0
4.2 特殊参数变量
(1)命令行参数个数
$#
特殊变量,含有命令行参数的个数,对程序名不计数。 可以和普通变量一样使用。
echo "there are $# paremeters"
使用if-then语句用test命令行提供的参数总数执行数值测试,如果参数总是不对,可以打印一条错误消息说明脚本的正确用法。
(2)命令行参数
$*
变量,将命令行上提供的所有参数当作单个单词保存。
$@
变量,将命令行上提供的所有参数当作字符串保存。可以使用for
命令遍历所有的值。
IFS='\n' for para in $@ do echo $para done
4.3 移动变量
4.4 处理选项
(1)使用getopt
命令:接受一系列任意形式的命令行选项和参数,并自动转换成适当的格式。
getopt optstring options parameters
(2)使用getopts
命令
4.5 获得用户输入(read命令)
read
命令:接受从标准输入(键盘)或文件描述符的输入,并将数据放在一个或多个变量中。
read命令选项 作用 示例 -p 允许直接在read命令行指定提示符 read -p "please enter your name: " name
-t 指定read命令等待输入的秒数 read -t 5 var
-s 隐藏读取的数据(用于密码等) read -s -p "please enter your code: " code
从文件中读取数据,最常见的方法:将文件运行cat
命令后的输出通过管道直接传给含有read
命令的while
命令,例如
#!/bin/bash
#read from file
cnt=0
cat input.file | while read line
do
cnt=$[$cnt+1]
echo "line $cnt is: $line"
done
exit 0
5. 呈现数据
1. 标准文件描述符
bash shell 保留了最早的3个文件描述符(0、1、2)
文件描述符 缩写 描述 0 SIDIN 标准输入 1 STDOUT 标准输出 2 STDERR 标准错误
2. 重定向
默认情况下,linux会将STDERR定向到STDOUT.
重定向标准输出:
cat inputfile 1> outfile
重定向标准错误:
cat not_exist_file 2> errfile
重定向数据和错误1:
cat inputfile not_exist_file 1> outfile 2> errfile
重定向数据和错误2:使用特殊的重定向符号&>
cat inputfile not_exist_file &>err_out_file
3. 在脚本中重定向输出
3.1 临时重定向每行输出
在重定向到文件描述符时,必须在文件描述符数字之前加一个and符号(&)
这个方法非常适合在脚本中生成错误消息。
#!/bin/bash
#chong ding xiang
#将这行输出重定向到“错误输出”
echo "this is an err msg" >&2
#将这行输出重定向到指定文件
echo "this is a normal output to file" > out_file
#正常输出
echo "this is a normal output"
exit 0
运行时,指定文件描述符重定向的位置(文件),例如: ./bashfile 2> errfile
3.2 永久重定向脚本中的所有命令
exec
命令:告诉shell脚本在运行期间,重定向某个特定文件描述符。
#!/bin/bash
#chong ding xiang
#将标准输出重定向到指定文件
exec 1> stdoutfile
echo "this is a normal output"
exit 0
4. 在脚本中重定向输入
exec 0< input_file
#之后,当使用read命令时,则直接重input_file中读取
5. 创建自己的重定向
在shell中最多可以有9个打开的文件描述符。
5.1 创建输出文件描述符
exec 3>out3_file
echo "this should be stored in the file" >&3
5.2 重定向文件描述符
5.3 创建输入文件描述符
在重定向到文件之前,先将STDIN文件描述符保存到另外一个文件描述符,然后在读取完文件之后将STDIN恢复到它原来的位置
#保存
exec 6<&0
#重定向
exec 0<input_file
#do something
#...
#恢复
exec 0<&6
5.4 创建读写文件描述符
在向同一个文件进行读写数据操作,shell维护一个内部指针,指明现在在文件中的位置,任何读写都会从文件指针上次保存的位置开始。
exec 3<> in_and_out_file
echo "this is a line" >&3
read line <&3
echo $line
5.5 关闭文件描述符
- shell会在脚本退出时,自动关闭。
- 当需要在shell退出前关闭文件描述符,需要手动
exec 3>$-
6. 列出打开的文件描述符
lsof
命令:输出整个linux系统打开的所有文件描述符。
选项 含义 -p 指定进程ID -d 指定要显示的文件描述符个数 -a 对其他两个选项的结果执行布尔AND运算
7. 阻止命令输出
当脚本作为后台进程执行时,不想显示脚本的输出。
阻止任何数据或错误消息而不保存它们的一个通用方法:将STDOUT或STDERR重定向到/dev/null
文件(特殊文件,null文件的任何数据都不会保存)。
./shellfile > /dev/null
8. 临时文件
/tmp
目录:linux系统留给临时文件的特殊目录位置,在系统启动时自动删除/tmp
目录的所有文件。
mktemp
命令:在本地目录中创建一个临时文件,返回创建临时文件的全路径。
mktemp tempfile.XXXXXX
在脚本中使用mktemp
命令时,将文件名保存到变量中,在后面的脚本中引用。
创建临时目录,需要使用-d
选项
mktemp -d dir.XXXXXX
9. 记录消息(tee命令)
tee – read from standard input and write to standard output and files