Shell脚本编程
一、构建基本脚本
1.使用美元符$可以引用一个变量,将命令输出赋给变量有两种方法,testing = `date`或者testing = $(date)
2.使用大于号(>)将命令的输出发送到一个文件中,例如:date > test6,可以创建一个文件test6,并将date命令的输出重定向到该文件中,如果输出文件已经存在,将用新的文件数据覆盖。
3.一个成功结束的命令的退出状态码是0,如果一个命令结束时有错误,退出状态码就是一个正数值。
4.默认情况下,shell脚本会以脚本中最后一个命令的退出码退出。可以使用exit命令+退出码重新定义脚本的退出状态码。
二、使用结构化命令
1.if-then语句的格式: if 语句会运行 if 后面的那个命令。如果该命令的退出状态码是 0(该命令成功运行),位于 then 部分的命令就会被执行。如果该命令的退出状态码是其他值, then部分的命令就不会被执行,bash shell会继续执行脚本中的下一个命令。 fi 语句用来表示 if-then语句到此结束。
if command then commands fi
2.if-then-else语句:当 if 语句中的命令返回退出状态码 0 时, then 部分中的命令会被执行,这跟普通的 if-then语句一样。当 if 语句中的命令返回非零退出状态码时,bash shell会执行 else 部分中的命令。
if command then commands else commands fi
3.elif语句:elif 语句行提供了另一个要测试的命令,这类似于原始的 if 语句行。如果 elif 后命令的退出状态码是 0 ,则bash会执行第二个 then 语句部分的命令。
if command1 then commands elif command2 then more commands fi
4.将多个elif语句串起来,形成一个大的if-then-elif嵌套组合:每块命令都会根据命令是否会返回退出状态码 0 来执行。记住,bash shell会依次执行 if 语句,只有第一个返回退出状态码 0 的语句中的 then 部分会被执行。
if command1 then command set 1 elif command2 then command set 2 elif command3 then command set 3 elif command4 then command set 4 fi
5.test 命令提供了在 if-then 语句中测试不同条件的途径。如果 test 命令中列出的条件成立,test 命令就会退出并返回退出状态码 0 。这样 if-then 语句就与其他编程语言中的 if-then 语句以类似的方式工作了。如果条件不成立, test 命令就会退出并返回非零的退出状态码,这使得if-then 语句不会再被执行。
if test condition then commands fi
bash shell提供了另一种条件测试方法,无需在 if-then 语句中声明 test 命令。方括号定义了测试条件。注意,第一个方括号之后和第二个方括号之前必须加上一个空格,否则就会报错。
test 命令可以判断三类条件: 数值比较、字符串比较、文件比较。
if [ condition ] then commands fi
6.test命令中的数值比较
n1 -eq n2 检查 n1 是否与 n2 相等 n1 -ge n2 检查 n1 是否大于或等于 n2 n1 -gt n2 检查 n1 是否大于 n2 n1 -le n2 检查 n1 是否小于或等于 n2 n1 -lt n2 检查 n1 是否小于 n2 n1 -ne n2 检查 n1 是否不等于 n2
7.test命令中的字符串比较
str1 = str2 检查 str1 是否和 str2 相同 str1 != str2 检查 str1 是否和 str2 不同 str1 < str2 检查 str1 是否比 str2 小 str1 > str2 检查 str1 是否比 str2 大 -n str1 检查 str1 的长度是否非0 -z str1 检查 str1 的长度是否为0
8.test命令中的文件比较
-d file 检查 file 是否存在并是一个目录 -e file 检查 file 是否存在 -f file 检查 file 是否存在并是一个文件 -r file 检查 file 是否存在并可读 -s file 检查 file 是否存在并非空 -w file 检查 file 是否存在并可写 -x file 检查 file 是否存在并可执行 -O file 检查 file 是否存在并属当前用户所有 -G file 检查 file 是否存在并且默认组与当前用户相同 file1 -nt file2 检查 file1 是否比 file2 新 file1 -ot file2 检查 file1 是否比 file2 旧
9.if-then语句允许使用布尔逻辑来组合测试,有两种布尔运算符可用:
[ condition1 ] && [ condition2 ]
[ condition1 ] || [ condition2 ]
10.双括号命令允许你在比较过程中使用高级数学表达式。格式:(( expression ))。 test 命令只能在比较中使用简单的算术操作。
val++后增 val--后减 ++val先增 --val先减 !逻辑求反 ~位求反 **幂运算 <<左位移 >>右位移 &位布尔和 |位布尔或 &&逻辑和 ||逻辑或
11.双方括号命令提供了针对字符串比较的高级特性。双方括号命令的格式如下:[[ expression ]]。双方括号里的 expression 使用了 test 命令中采用的标准字符串比较。但它提供了 test 命
令未提供的另一个特性——模式匹配(pattern matching)。
12. case 命令,就不需要再写出所有的 elif 语句来不停地检查同一个变量的值了。 case 命令会采用列表格式来检查单个变量的多个值。
case variable in pattern1 | pattern2 ) commands1 ;; pattern3 ) commands2 ;; *) default commands ;; esac
三、更多的结构化命令
1.for命令-基于列表
for test in Alabama Alaska Arizona Arkansas California Colorado do echo The next state is $test done
2.for命令-基于数月表达式
for (( i=1; i <= 10; i++ )) do echo "The next number is $i" done
使用多个变量
for (( a=1, b=10; a <= 10; a++, b-- )) do echo "$a - $b" done
3.while命令:while 命令某种意义上是 if-then 语句和 for 循环的混杂体。 while 命令允许定义一个要测试的命令,然后循环执行一组命令,只要定义的测试命令返回的是退出状态码 0 。它会在每次迭代的一开始测试 test 命令。在 test 命令返回非零退出状态码时, while 命令会停止执行那组命令。
while test command do other commands done
例如:
var1=10 while [ $var1 -gt 0 ] do echo $var1 var1=$[ $var1 - 1 ] done
使用多个测试条件
var1=10 while echo $var1 [ $var1 -ge 0 ] do echo "This is inside the loop" var1=$[ $var1 - 1 ] done
4.until 命令和 while 命令工作的方式完全相反。 until 命令要求你指定一个通常返回非零退出状态码的测试命令。只有测试命令的退出状态码不为 0 ,bash shell才会执行循环中列出的命令。一旦测试命令返回了退出状态码 0 ,循环就结束了。
until test commands do other commands done
例如:
var1=100 until [ $var1 -eq 0 ] do echo $var1 var1=$[ $var1 - 25 ] done
5.嵌套循环
for (( a = 1; a <= 3; a++ )) do echo "Starting loop $a:" for (( b = 1; b <= 3; b++ )) do echo " Inside loop: $b" done done
6.遍历存储在文件中的数据。使用嵌套循环和修改IFS环境变量结合。通过修改 IFS 环境变量,就能强制 for 命令将文件中的每行都当成单独的一个条目来处理,即便数据中有空格也是如此。一旦从文件中提取出了单独的行,可能需要再次利用循环来提取行中的数据。典型的例子是处理/etc/passwd文件中的数据。这要求你逐行遍历/etc/passwd文件,并将 IFS变量的值改成冒号,这样就能分隔开每行中的各个数据段了。
IFS.OLD=$IFS IFS=$'\n' for entry in $(cat /etc/passwd) do echo "Values in $entry –" IFS=: for value in $entry do echo " $value" done done
这个脚本使用了两个不同的 IFS 值来解析数据。第一个 IFS 值解析出/etc/passwd文件中的单独的行。内部 for 循环接着将 IFS 的值修改为冒号,允许你从/etc/passwd的行中解析出单独的值。
7.break命令是退出循环的一个简单方法。可以用 break 命令来退出任意类型的循环,包括while 和 until 循环。
1.跳出单个循环 for var1 in 1 2 3 4 5 6 7 8 9 10 do if [ $var1 -eq 5 ] then break fi echo "Iteration number: $var1" done echo "The for loop is completed" for 循环通常都会遍历列表中指定的所有值。但当满足 if-then 的条件时,shell会执行 break 命令,停止 for 循环。 2.跳出内部循环:在处理多个循环时, break 命令会自动终止你所在的最内层的循环。 for (( a = 1; a < 4; a++ )) do echo "Outer loop: $a" for (( b = 1; b < 100; b++ )) do if [ $b -eq 5 ] then break fi echo " Inner loop: $b" done done 内部循环里的 for 语句指明当变量 b 等于100时停止迭代。但内部循环的 if-then 语句指明当变量 b 的值等于5时执行 break 命令。注意,即使内部循环通过 break 命令终止了,外部循环依然继续执行。 3.跳出外部循环 有时你在内部循环,但需要停止外部循环。 break 命令接受单个命令行参数值:break n 其中 n 指定了要跳出的循环层级。默认情况下, n 为 1 ,表明跳出的是当前的循环。如果你将n 设为 2 , break 命令就会停止下一级的外部循环。 $ cat test20 #!/bin/bash # breaking out of an outer loop for (( a = 1; a < 4; a++ )) do echo "Outer loop: $a" for (( b = 1; b < 100; b++ )) do if [ $b -gt 4 ] then break 2 fi echo " Inner loop: $b" done done $ ./test20 Outer loop: 1 Inner loop: 1 Inner loop: 2 Inner loop: 3 Inner loop: 4 $ 注意,当shell执行了 break 命令后,外部循环就停止了。
8.continue 命令可以提前中止某次循环中的命令,但并不会完全终止整个循环。可以在循环内部设置shell不执行命令的条件。
$ cat test21 #!/bin/bash # using the continue command for (( var1 = 1; var1 < 15; var1++ )) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done $ ./test21 Iteration number: 1 Iteration number: 2 Iteration number: 3 Iteration number: 4 Iteration number: 5 Iteration number: 10 Iteration number: 11 Iteration number: 12 Iteration number: 13 Iteration number: 14 $
当 if-then 语句的条件被满足时(值大于5且小于10),shell会执行 continue 命令,跳过此次循环中剩余的命令,但整个循环还会继续。当 if-then 的条件不再被满足时,一切又回到正轨。也可以在 while 和 until 循环中使用 continue 命令,但要特别小心。记住,当shell执行continue 命令时,它会跳过剩余的命令。如果你在其中某个条件里对测试条件变量进行增值,问题就会出现。
和 break 命令一样, continue 命令也允许通过命令行参数指定要继续执行哪一级循环:continue n
9.处理循环的输出。在shell脚本中,你可以对循环的输出使用管道或进行重定向。这可以通过在 done 命令 之后添加一个处理命令来实现。
for file in /home/rich/* do if [ -d "$file" ] then echo "$file is a directory" elif echo "$file is a file" fi done > output.txt shell会将 for 命令的结果重定向到文件output.txt中,而不是显示在屏幕上。
这种方法同样适用于将循环的结果管接给另一个命令。
$ cat test24 #!/bin/bash # piping a loop to another command for state in "North Dakota" Connecticut Illinois Alabama Tennessee do echo "$state is the next place to go" done | sort echo "This completes our travels" $ ./test24 Alabama is the next place to go Connecticut is the next place to go Illinois is the next place to go North Dakota is the next place to go Tennessee is the next place to go This completes our travels $ state 值并没有在 for 命令列表中以特定次序列出。 for 命令的输出传给了 sort 命令,该命 令会改变 for 命令输出结果的顺序。运行这个脚本实际上说明了结果已经在脚本内部排好序了。
四、处理用户输入
五、呈现数据
六、控制脚本
七、创建函数