文章目录
  1. 1. 准备
    1. 1.1. 关于替换
    2. 1.2. Unix 命令
    3. 1.3. Here Documents
  2. 2. 控制语句
    1. 2.1. 条件测试
    2. 2.2. 循环
    3. 2.3. 选择
  3. 3. demo
    1. 3.1. grep
    2. 3.2. sed
    3. 3.3. 文件重命名
    4. 3.4. 日志重命令
  4. 4. 小结
  5. 5. 参考

Linux 下有很多不同的 shell,但我们通常使用 bash (bourne again shell) 进行 shell 编程,因为 bash 是免费的,且易用。下面用到的例子,都是用 bash。

程序的第一行必须是 #!/bin/sh

1
2
3
4
5
6
7
#!/bin/sh
# #! 用来告诉系统,它后面的参数是用来执行改文件的程序。我们使用 /bin/sh
# 在 shell 下,所有变量都用字符串表示,变量不需要声明,直接使用,直接对变量进行赋值。
# 在 shell 中,可以使用任意的 Linux/Unix 命令。比如
# ls cp | grep > >>
# if ;then else if then else fi

如果要执行脚本,就必须使其具有执行权限。

1
chmod +x demo.sh

执行

1
2
3
4
5
# 可以
sh demo.sh
# 也可以
./demo.sh

准备

关于替换

关于替换(or扩展),举例说明,eg. echo *.jpg
不带引号,是命令;
带了引号,会当作字符串(可以使用转义字符-反斜杠,来防止通配符的扩展)

其中:
单引号:会防止任何变量扩展,即就是纯字符串
双引号:可以防止通配符扩展,但允许变量扩展。即里面可以携带变量

在双引号里,也可以使用{}来告诉我们要打印的是个变量

Unix 命令

常见命令

1
2
3
4
ls # 文件列表
find # 搜索文件 find *.txt
cd ../
cd directory
1
2
3
4
5
echo 'hello word'
cat file.txt # 输出文件内容到标准输出设备(屏幕)上
head file # 打印文本文件开头几行
tail file # 打印文本文件末尾几行
1
2
3
4
5
6
rm file # 删除文件
cp sourcefile destfile # 文件拷贝
mv oldname newname # 重命名文件或移动文件
mkdir foldername # 新建文件夹
rmdir foldername # 删除文件夹
1
2
3
4
5
6
sed
# sed 是一个基本的查找替换程序。
# 可以从标准输入(比如命令管道)读入文本,并将结果输出到标准输出(屏幕)
# 该命令采用正则表达式进行搜索
# 比如将文件demo.txt中的anjia替换成ANJIA,并将替换的内容输出到demo2.txt
# cat demo.txt | sed 's/anjia/ANJIA/' > demo2.txt
1
2
3
4
5
6
7
awk # 用来从文本文件中提取字段
grep 'pattern' file # 在文件内搜索字符串比如:grep 'searchstring' file.txt
sort file.txt # 对file.txt文件中的行进行排序
uniq # 删除文本文件中出现的行列比如: sort file.txt | uniq
read var # 提示用户输入,并将输入赋值给变量
wc –l filewc -w filewc -c file # 计算文件行数计算文件中的单词数计算文件中的字符数

其他:

1
2
3
# 管道 | 将一个命令的输出作为另外一个命令的输入
# > 写入文件并覆盖旧文件
# >> 加到文件的尾部,保留旧文件内容

Here Documents

在 bash 中使用多行注释的方法 Here Documents
其中,InputComesFromHERE 是自定义字符串,运算符
<< 内部内容必须顶格
<<- 内部内容可以有缩进

1
2
3
4
5
command <<InputComesFromHERE
...
...
...
InputComesFromHERE
1
2
3
4
5
command <<-InputComesFromHERE
...
...
...
InputComesFromHERE

:是空命令,结合 here Documents,那么以下是多行注释

1
2
3
:<<Multi-Comment
听说这里可以写成多行注释,试试喽
Multi-Comment

参考:
http://tldp.org/LDP/abs/html/here-docs.html
http://blog.csdn.net/delphiwcdj/article/details/8088407

控制语句

条件测试

[ ] 来表示条件测试,注意方括号和中间的内容之间必须有空格

1
2
3
4
[ -n "$var" ] # 判断$var变量是否有值
[ "$a" = "$b" ] # 判断$a和$b是否相等
[ -f "somefile" ] # 判断是否是一个文件
[ -x "/bin/ls" ] # 判断/bin/ls是否存在并有可执行权限

更多条件测试,可参考 shell中条件判断if中的-a到-z的意思

if-else

1
2
3
4
5
if [ xxx ]; then
...
else
...
fi

case-in

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 执行命令
ftype=`file "$1"`
echo $ftype
# case...in...esac
case "$ftype" in
"$1: Zip archive"*) # seems to string indexOf match
unzip "$1";;
"$1: gzip compressed"*)
gunzip "$1";;
"$1: bzip2 compressed"*)
bunzip2 "$1";;
# *) error "File $1 can not be uncompressed with smartzip";;
esac

循环

for-in

1
2
3
for var in A B C; do
echo "var is $var"
done

while

1
2
3
4
while true do
sh /Users/anjia/GitHub/shell/crontab.sh
sleep 5
done

选择

可与用户交互的 select

1
2
3
4
5
#!/bin/sh
select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do
break
done
echo "You have select $var"

执行结果

demo

下面用实例来感受下 shell 脚本。在看 demo 之前,先了解下几个有特殊含义的参数:

  1. $* 所有输入的命令行参数值
  2. $1-$9 命令行的第1个参数、…、第9个参数
  3. $# 命令行参数的总个数

grep

grep:在文件内搜索字符串
wc:计算文件行数|文件单词个数
>>:文件追加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/sh
echo 'welcome to shell!'
grep 'anjia' filename1.txt
grep 'anjia' filename1.txt | wc -l
grep 'anjia' filename1.txt | wc -l >> filename2.txt
if [ -f 'filename2.txt' ];then
echo 'filename2.txt is a file.'
else
echo 'filename2.txt is not a file.'
fi
exit 1

运行结果:

sed

sed:基本的查找替换程序。从标准输入(eg命令管道)读入文本,并将结果输出到标准输出(屏幕)。此命令采用正则表达式进行搜索。
>:文件重写覆盖

文件重命名

本例子是对多个文件进行重命名的。其中:
第一个参数:oldname
第二个参数:newname
之后的参数:将要替换的文件列表

直接看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/bin/sh
# $# 包含命令行参数的总个数
if [ $# -lt 3 ]; then
# 将帮助文字传递给 cat
cat <<-HELP
ren -- renames a number of files using sed regular expressions
USAGE: ren 'regexp' 'replacement' files...
EXAMPLE: rename all *.HTM files in *.html:
ren 'HTM$' 'html' *.HTM
HELP
# 多行multi-line message using cat
exit 0 # 退出程序
fi
OLD="$1" # 第一个参数赋值给OLD
NEW="$2" # 第二个参数赋值给NEW
shift
shift # remove one argument from the list of command line arguments
# 将第一个和第二个参数从参数列表中删除
# 于是,原来的第三个参数,就成了参数列表$*中的第一个参数
# $* 参数列表
for file in $*; do
if [ -f "$file" ]; then
newfile=`echo "$file"|sed "s/${OLD}/${NEW}/g"`
# sed 命令:搜索和替换
# 将反斜线内命令结果赋值给变量 newfile
# 于是,我们就达到了目的:得到了旧文件名和新文件名
if [ -f "$newfile" ]; then
echo "ERROR: $newfile exists already"
else
echo "renaming $file to $newfile ..."
mv "$file" "$newfile"
# mv oldname newname 重命名文件|移动文件
fi
fi
done
exit 1

运行结果:

日志重命令

本实是给日志文件列表再插入一个最新的日志,从头插。比如:有如下文件
log.txt.1 log.txt.2 log.txt.3
现在又产生了一个最新的日志 log.txt,我们要将其变成 log.txt.1,原有的 log.txt.1变成 log.txt.2,log.txt.2 变成 log.txt.3,依次类推。

直接看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/bin/sh
ver="0.1"
help(){
cat <<-HELP
rotatefile -- rotate the file name
USAGE: rotatefile [-h] filename
OPTIONS: -h help text
EXAMPLE: rotatefile out
This will e.g rename out.2 to out.3,out1 to out.2
and create an empty out-file
The max number is 10
version $ver
HELP
exit 0
}
error(){
echo "$1"
exit 0
}
# while [ -n "$1" ]; do
# case $1 in
# -h) help;shift 1;;
# # --) exit 1;
# # -*) echo "error: no such option $1. -h for help"; exit 1;;
# # *) break;;
# esac
# done
# input check
# string 长度为0则真
if [ -z "$1" ]; then
error "ERROR: you must specify a file, use -h for help"
fi
filen="$1"
echo $filen
# rename any.1 .2 etc file: 10 9 8 7 6 5 4 3 2
for n in 5 4 3 2 1; do
if [ -f "$filen.$n" ]; then
p=`expr $n + 1`
echo "mv $filen.$n $filen.$p"
mv $filen.$n $filen.$p
fi
done
# rename the original file:
if [ -f "$filen" ]; then
echo "mv $filen $filen.1"
mv $filen $filen.1
fi
echo touch $filen
touch $filen
exit 1

运行结果:

小结

在编写 shell 脚本时,最好…:

  1. 写注释
  2. 校验参数
  3. 支持帮助说明,即选项 -h 或者 -help
    包括:功能说明、USAGE、OPTIONS、EXAMPLE

学新语言时,一个一个字符敲代码的感觉,很好。

参考

http://blog.chinaunix.net/uid-20328094-id-95121.html

shell
bash

文章目录
  1. 1. 准备
    1. 1.1. 关于替换
    2. 1.2. Unix 命令
    3. 1.3. Here Documents
  2. 2. 控制语句
    1. 2.1. 条件测试
    2. 2.2. 循环
    3. 2.3. 选择
  3. 3. demo
    1. 3.1. grep
    2. 3.2. sed
    3. 3.3. 文件重命名
    4. 3.4. 日志重命令
  4. 4. 小结
  5. 5. 参考