学习shell程序设计的方法就是:动手 + man command
下面脚本全部是在Cygwin下测试的。
$ /bin/bash --version
GNU bash, version 2.05b.0(1)-release (i686-pc-cygwin)
Copyright (C) 2002 Free Software Foundation, Inc.
编写shell脚本程序有两种方式:
【1】可以输入一系列命令让shell交互地执行它们。
【2】可以把这些命令保存到一个文件中,然后将该文件作为一个程序来调用。
Bash常用命令
目录:
(1) read命令 —— 变量内容由用户决定
(2) 重定向输出和输入
(3) 管道 |
(4) find命令 —— 在系统中,搜索文件
(5) grep命令 —— 在文件中,搜索字符串
(6) -exec 和 -ok 命令
(7) 算术扩展
(8) 参数扩展
(9) 脚本的追踪与调试
(1) read命令 —— 变量内容由用户决定
例子:
#! /bin/bash
# program:
# This program is used to show the usage of [read] command.
# History:
# 2011/04/23 wcdj First release
echo -e "This program is used to show the usage of [read] command."
read -p "Please input your first name: " firstname
read -p "Please input your last name: " lastname
echo -e "/nYour full name is: $firstname $lastname"
(2) 重定向输出和输入
重定向输出 > 和 >>
文件描述符0:代表一个程序的标准输入
文件描述符1:代表一个程序的标准输出
文件描述符2:代表一个程序的标准错误输出。
重定向输入 <
(3) 管道 |
可以使用管道操作符 | 来连接进程。Linux与MS-DOS不同,在Linux下通过管道连接的进程可以同时运行,并且随着数据流在它们之间的传递可以自动地进行协调。
例子1:使用sort命令对ps命令的输出进行排序。
ps | sort > pssort.out # 方法1:将结果保存到pssort.out文件中
ps | sort | more # 方法2:在屏幕上分页显示输出结果
例子2:查看系统中运行的所有进程的名字,但不包括shell本身
ps -xo comm | sort | uniq | grep -v sh | more
Cygwin下ps没有 -xo 选项。
注意:
(1) 允许连接的进程数目是没有限制的。
(2) 如果有一系列命令需要执行,相应的输出文件是在这一组命令被创建的同时立刻被创建或写入的,所以决不要在命令流中重复使用相同的文件名。比如下面这条命令:
cat mydata.txt | sort | uniq > mydata.txt
错误:最终将得到一个空文件,因为在读取文件mydata.txt之前就已经覆盖了这个文件的内容。
(4) find命令 —— 在系统中,搜索文件
find命令的完整语法格式如下:
find [path] [options] [tests] [actions]
例子1:在本地机器上查找名为test的文件,为了确保具有搜索整个机器的权限,请以root用户身份来执行这个命令。
# find /home/wcdj -name test -print
输出结果:
/home/wcdj/linux/openssl-SNAP-20091203/demos/tunala/test.sh
/home/wcdj/bash/test.sh
执行后,硬盘会疯狂的转动,需要花费很长的时间。
例子2:在当前目录中搜索比文件file要新的文件,如果这个测试通过,然后再测试这个文件是否是一个普通文件,最后,确认搜索到的文件。
find . /( -name "*" -or -newer file /) -type f -print
注意:
(1) 使用圆括号来强制测试和操作符的优先级,由于圆括号对shell来说有其特殊的含义,所以还必须使用反斜线来引用圆括号。
(2) -name pattern 文件名(不包括路径名)匹配提供的模式pattern,为了确保pattern被传递给find命令而不是由shell来处理,pattern必须总是用引号括起。
(5) grep命令 —— 在文件中,搜索字符串
grep命令的完整语法格式如下:
grep [options] PATTERN [FILES]
例子1:从大量C语言源文件中查找包含字符串POSIX的文件,并输出符合条件的文件名。
$ more `grep -l POSIX *` # 方法1:使用反引号
$ more $(grep -l POSIX *) # 方法2:使用$(...)获取子进程的输出
$ grep -l POSIX * | more # 方法3:使用管道 |
$ grep -l POSIX * -exec more {} /; # 方法4:使用-exec(可以显示但会输出一些错误)
例子2:
grep wcdj words.txt # 在words.txt文件中搜索字符串wcdj,然后输出匹配的行
grep -c wcdj words.txt words2.txt # 在两个不同的文件中计算匹配行的数目。在这种情况下,文件名被输出
grep -c -v wcdj words.txt words2.txt # 使用-v选项对搜索取反,在两个文件中计算不匹配行的数目
例子3:使用正则表达式,实现更复杂的匹配
# [1] 查找以字母e结尾的行
grep e$ words.txt
# [2] 查找以字母a结尾的单词
grep a[[:blank:]] words.txt
# [3] 查找以Th开头的3个字母组成的单词
grep Th.[[:blank:]] words.txt
# [4] 使用扩展grep模式来搜索只有10个字符长的全部由小写字母组成的单词
grep -E [a-z]/{10/} words.txt
(6) -exec 和 -ok 命令
-exec 和 -ok 命令将命令行上后续的参数作为它们参数的一部分,直到被 /; 序列终止。实际上,-exec 和 -ok 命令执行的是一个嵌入式命令,所以嵌入式命令必须以一个转义的分号结束,使得find命令可以决定什么时候它可以继续查找用于它自己的命令行选项。魔术字 符串{}是-exec或-ok命令的一个特殊类型的参数,它将被当前文件的完整路径取代。
例子:
find . -name file -type f -exec ls -l {} /;
find . -newer file -type f -exec ls -l {} /;
(7) 算术扩展
expr命令可以处理一些简单的算术命令,但这个命令执行起来相当慢,因为它需要调用一个新的shell来处理expr命令。
一种更新更好的办法是使用$((...))扩展计算表达式的值。
注意:
$((...))与$(...)不同,两对圆括号用于算术替换,而一对圆括号用于命令的执行和获取输出。
例子:打印输出0~9
#! /bin/bash
# program:
# $((...))
# History:
# 2011/04/23 wcdj First release
x=0;
while [ "$x" -ne 10 ]
do
echo $x
x=$(($x+1)) # x=$(expr $x+1)
done
exit 0
(8) 参数扩展
将变量放在花括号{}中,实现把参数的值替换进一个字符串里。
例子1:
#! /bin/bash
# program:
# 参数扩展
# History:
# 2011/04/23 wcdj First release
for i in 1 2
do
echo ${i}_tmp
done
例子2:使用cjpeg程序将当前目录中的每一个的GIF文件创建一个对应的JPGE文件
#! /bin/bash
# program:
# 参数扩展
# History:
# 2011/04/23 wcdj First release
for image in *.gif
do
cjpeg $image > $(image%%gif)jpg
done
注意:
关于参数扩展的使用方法很多,更多使用方法见参考文献[2]中P.60。
(9) 脚本的追踪与调试
sh -[nvx] scripts.sh
参数的意义:
-n:不要执行脚本,仅查询语法问题,若没有语法问题,则不会显示任何信息
-v:在执行脚本前,先将脚本的内容输出到屏幕上
-x:将使用的脚本内容显示到屏幕上,这是很有用的参数。使用 -x 是追踪脚本的好方法,它可以在执行前列出所有执行的程序段,如果是程序段落,则输出时,最前面会加上 + 符号,表示它是程序代码,实际的输出则与标准输出有关。
例子:下面这个脚本文件的名字为test.sh
#! /bin/bash
# program:
# 参数扩展
# History:
# 2011/04/23 wcdj First release
for i in 1 2
do
echo ${i}_tmp
done
调试这个脚本:
sh -x test.sh
显示如下内容:
+ echo 1_tmp
1_tmp
+ echo 2_tmp
2_tmp
待续……
参考:
[1] Linux鸟哥的私房菜基础学习篇(第二版)
[2] Linux程序设计(第4版)