介绍基本的shell编程方法,参考的教程是Linux Shell Scripting Tutorial, A Beginner’s handbook。
变量
变量是代码的基本组成元素。可以认为shell中的变量类型都是字符串。
shell中的变量可以分为两类:系统变量和用户自定义变量。下面分别进行介绍。
在代码中使用变量值的时候,需要在前面加上$
。echo
命令可以在控制台打印相应输出。所以使用echo $var
就可以输出变量var
的值。
系统变量
系统变量是指Linux中自带的一些变量。例如HOME
,PATH
等。其中PATH
又叫环境变量。更多的系统变量见下表:
用户定义的变量
用户自定义变量是用户命名并赋值的变量。使用下面的方法定义:
1 | # 注意不要在等号两边插入空格 |
局部变量和全局变量
局部变量是指在当前代码块内可见的变量,使用local
声明。例如下面的代码,将依次输出:111, 222, 111.1
2
3
4
5
6
7
8
9
10
11
num=111 # 全局变量
func1()
{
local num=222 # 局部变量
echo $num
}
echo "before---$num"
func1
echo "after---$num"
变量之间的运算
使用expr
可以进行变量之间的运算,如下所示:
1 | # 注意要在操作符两边空余空格 |
``和””
使用``(也就是TAB键上面的那个)包起来的部分,是可执行的命令。而使用””(引号)包起来的部分,是字符串。
1 | a=`expr 10 \* 3` |
另外,使用””(双引号)括起来的字符串会发生变量替换,而用’’(单引号)括起来的字符串则不会。
1 | a=1 |
读取输入
使用read var1, var2, ...
的方式从键盘的输入读取变量的值。
1 | # input a=1 |
基本概念
命令的返回值
当bash命令成功执行后,返回给系统的返回值为0
;否则为非零。可以据此判断上步操作的状态。使用$?
可以取出上一步执行的返回值。
1 | # 将echo 错输为ecoh |
通配符
通配符是指*
,?
和[...]
这三类。
*
可以匹配任意多的字符,?
用来匹配一个字符。[...]
用来匹配括号内的字符。见下表。
[...]
表示法还有如下变形:
- 使用
-
用来指示范围。如[a-z]
,表示a
到z
间任意一个字符。 - 使用
^
或!
表示取反。如[!a-p]
表示除了a
到p
间字符的其他字符。
输入输出重定向
重定向是指改变命令的输出位置。使用>
进行输出重定向。使用<
进行输入重定向。例如,ls -l > a.txt
,将本目录下的文件信息输出到文本文件a.txt
中,而不再输出到终端。
此外,>>
同样是输出重定向。但是它会在文件末尾追加写入,不会覆盖文件的原有内容。
搭配使用<
和>
可以做文件处理。例如,tr group1 group2
命令可以将group1
中的字符变换为group2
中对应位置的字符。使用如下命令:
1 | tr "[a-z]" "A-Z" < ori.txt > out.txt |
可以将ori.txt
中的小写字母转换为大写字母输出到out.txt
中。
管道(pipeline)
管道|
可以将第一个程序的输出作为第二个程序的输入。例如:
1 | cat ori.txt | tr "[a-z]" "A-Z" |
会将ori.txt
中的小写字母转换为大写,并在终端输出。
过滤器(Filter)
Filter是指那些输入和输出都是控制台的命令。通过Filter和输入输出重定向,可以很方便地对文件内容进行整理。例如:
1 | sort < names.txt | uniq > u_names.txt |
uniq
命令可以实现去重,但是需要首先对输入数据进行排序。上面的Filter可以将输入文件names.txt
中的行文本去重后输出到u_names.txt
中去。
控制流
if 条件控制
在bash中使用if
条件控制的语法和MATLAB等很像,要在末尾加上类似end
的指示符,如下:
1 | if condition |
或者加上else
,使用如下的形式:1
2
3
4
5
6
7
8
9if condition
then
do something
elif condition
then
do something
else
do something
fi
那么,如何做逻辑运算呢?需要借助test
关键字。
对于整数来说,我们可以使用if test op1 oprator op2
的方式,判断操作数op1
和op2
的大小关系。其中,operator
可以是-gt
,-eq
等。
或者另一种写法:if [ op1 operator op2 ]
,但是注意后者[]
与操作数之间有空格。
如下表所示(点击可放大):
对于字符串,支持的逻辑判断如下:
举个例子,我们想判断输入的值是否为1或2,可以使用如下的脚本。注意[]
的两边一定要加空格。1
2
3
4
5
6
7
8
9
10
11
a=1
if [ $1=$a ]
then
echo "you input 1"
elif [ $1=2 ]
then
echo "you input 2"
else
echo "you input $1"
fi