Linux基础知识(4)- Shell (二) | Shell 数组、流程控制
1. Shell 数组
1) 定义数组
数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小。与大部分编程语言类似,数组元素的下标由 0 开始。
Shell 数组用括号来表示,元素用"空格"符号分割开,语法格式如下:
test_array=(value1 value2 ... valuen)
示例
test_array=(A B 'C' "D")
也可以使用数字下标来定义数组:
test_array[0]=A
test_array[1]=B
test_array[2]='C'
test_array[3]="D"
注:赋值时等号两边不能有空格。
2) 读取数组
语法格式如下:
${test_array[index]}
通过数字索引读取数组元素,示例如下。
echo "test_array[2]: ${test_array[2]}"
执行脚本,输出结果如下:
test_array[2]: C
3) 关联数组
Bash 支持关联数组,可以使用任意的字符串、或者整数作为下标来访问数组元素。
关联数组使用 declare 命令来声明,语法格式如下:
declare -A array_name
-A 选项就是用于声明一个关联数组。关联数组的键是唯一的。
示例
declare -A website=(["google"]="www.google.com", ["cnblogs"]="www.cnblogs.com", ["taobao"]="www.taobao.com")
也可以先声明一个关联数组,然后再设置键和值:
declare -A website
website["google"]="www.google.com"
website["cnblogs"]="www.cnblogs.com"
website["taobao"]="www.taobao.com"
访问关联数组元素可以使用指定的键,格式如下:
array_name["key"]
示例
echo "website['cnblogs']: ${website["cnblogs"]}"
执行脚本,输出结果如下:
website['cnblogs']: www.cnblogs.com
4) 获取数组中的所有元素
使用 @ 或 * 可以获取数组中的所有元素,示例如下。
echo "test_array[*]: ${test_array[*]}"
echo "test_array[@]: ${test_array[@]}"
echo "website[*]: ${website[*]}"
echo "website[@]: ${website[@]}"
执行脚本,输出结果如下:
test_array[*]: A B C D
test_array[@]: A B C D
website[*]: www.google.com www.cnblogs.com www.taobao.com
website[@]: www.google.com www.cnblogs.com www.taobao.com
5) 获取数组中的所有 Key
在数组前加一个感叹号 ! 可以获取数组的所有键,示例如下。
echo "!website[*]: ${!website[*]}"
echo "!website[@]: ${!website[@]}"
执行脚本,输出结果如下:
!website[*]: google runoob taobao
!website[@]: google runoob taobao
6) 获取数组的长度
获取数组长度的方法与获取字符串长度的方法相同,示例如下。
echo "#test_array[*]: ${#test_array[*]}"
echo "#test_array[@]: ${#test_array[@]}"
执行脚本,输出结果如下:
#test_array[*]: 4
#test_array[@]: 4
2. 流程控制
1) if 语句
(1) 单个分支 (if)
语法格式:
if condition
then
command1
command2
...
fi
if 和 then 放在同一行:
if condition; then
command1
command2
...
fi
写成一行(适用于终端命令提示符):
if condition; then command1; command2; fi
末尾的 fi 就是 if 倒过来拼写。
(2) 两个分支 (if else)
语法格式:
if condition
then
command1
command2
...
else
command
fi
(3) 多个分支 (if else-if else)
语法格式:
if condition1
then
command1
elif condition2
then
command2
else
command3
fi
(4) 判断语句
如果使用 [ ] 作为判断语句,大于使用 -gt,小于使用 -lt。
if [ "$a" -gt "$b" ]; then
...
fi
如果使用 (( )) 作为判断语句,大于使用 >,小于使用 <。
if (( a > b )); then
...
fi
(5) 示例
比较两个变量的大小,使用 [ ] 作为判断语句。
1 #!/bin/bash 2 3 a=10 4 b=20 5 if [ $a == $b ]; then 6 echo "a 等于 b" 7 elif [ $a -gt $b ]; then 8 echo "a 大于 b" 9 elif [ $a -lt $b ]; then 10 echo "a 小于 b" 11 else 12 echo "没有符合的条件" 13 fi
使用 (( )) 作为判断语句。
1 #!/bin/bash 2 3 a=10 4 b=20 5 if (( $a == $b )); then 6 echo "a 等于 b" 7 elif (( $a > $b )); then 8 echo "a 大于 b" 9 elif (( $a < $b )); then 10 echo "a 小于 b" 11 else 12 echo "没有符合的条件" 13 fi
输出结果都是:
a 小于 b
与 test 命令结合使用,如下所示:
#!/bin/bash
num1=$[2*3] # $[] 标识的是算术运算
num2=$[1+5]
if test $[num1] -eq $[num2]; then echo '两个数字相等'; fi
输出结果:
两个数字相等
2) for 循环
语法格式:
for var in item1 item2 ...
do
command1
command2
...
done
for 和 do 写在同一行:
for var in item1 item2 ...; do
command1
command2
...
done
写成一行:
for var in item1 item2 ... ; do command1; command2 ...; done;
当变量值在列表里,for 循环即执行一次所有命令,使用变量名获取列表中的当前取值。命令可为任何有效的 shell 命令和语句。in 列表可以包含替换、字符串和文件名。
示例
1 #!/bin/bash 2 3 for var in 1 2 3 4 do 5 echo "Value: $var" 6 done 7 8 for var in Hello world string; do 9 echo $var 10 done 11 12 for var in A 'B' "C"; do echo $var; done
输出结果:
1 Value: 1 2 Value: 2 3 Value: 3 4 Hello 5 world 6 string 7 A 8 B 9 C
3) while 循环
语法格式:
while condition
do
command1
command2
...
done
while 和 do 写在同一行:
while(( condition )); do
command1
command2
...
done
写成一行:
while(( condition )); do command1; command2 ...; done;
示例
1 #!/bin/bash 2 3 i=1 4 while(( $i<=3 )) 5 do 6 echo $i 7 let "i++" # let 命令,它用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量,具体可查阅:Bash let 命令。 8 done 9 10 while(( $i<=5 )); do 11 echo $i 12 i=`expr $i + 1` # expr 命令完成表达式的算术运算 13 done 14 15 echo '按下 <CTRL-D> 退出' 16 echo -n '输入一个字符: ' 17 while read a; do echo "输入的字符是:$a"; break; done
输出结果:
1 1 2 2 3 3 4 4 5 5 6 按下 <CTRL-D> 退出 7 输入一个字符: a 8 输入的字符是:a
4) 无限循环
语法格式:
while:
do
command1
command2
...
done
或
while true
do
command1
command2
...
done
或
for (( ; ; ))
5) until 循环
until 循环执行一系列命令直至条件为 true 时停止。until 循环与 while 循环在处理方式上刚好相反。
一般 while 循环优于 until 循环,但在某些时候(也只是极少数情况下),until 循环更加有用。
语法格式:
until condition
do
command1
command2
...
done
until 和 do 写在同一行:
until condition; do
command1
command2
...
done
写成一行:
until condition; do command1; command2; ...; done
示例
1 #!/bin/bash 2 3 i=1 4 until [ ! $i -lt 3 ] 5 do 6 echo $i 7 i=`expr $i + 1` 8 done 9 10 until [ ! $i -lt 6 ]; do 11 echo $i 12 i=`expr $i + 1` 13 done
输出结果:
1
2
3
4
5
6) case ... esac
case ... esac 是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case ... esac 语句,esac(就是 case 反过来)作为结束标记。
语法格式:
case 值 in
模式1)
command1
command2
...
;;
模式2)
command1
command2
...
;;
esac
case 工作方式如上所示,取值后面必须为单词 in,每一模式必须以右括号结束。取值可以为变量或常数,匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。
取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。
示例
1 #!/bin/bash 2 3 echo '输入 1 到 3 之间的数字:' 4 read aNum 5 case $aNum in 6 1) 7 echo '输入了 1' 8 ;; 9 2) 10 echo '输入了 2' 11 ;; 12 3) 13 echo '输入了 3' 14 ;; 15 *) 16 echo '没有输入 1 到 3 之间的数字' 17 ;; 18 esac 19 20 site="cnblogs" 21 case $site in 22 "cnblogs") 23 echo "CN Blogs" 24 ;; 25 "google") 26 echo "Google" 27 ;; 28 "taobao") 29 echo "Taobao" 30 ;; 31 esac
输出结果:
输入 1 到 3 之间的数字:
输入了 3
CN Blogs
7) 跳出循环
在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell 使用两个命令来实现该功能:break 和 continue。
(1) break 命令
break 命令允许跳出所有循环(终止执行后面的所有循环)。
下面的例子中,脚本进入死循环直至用户输入数字大于5。要跳出这个循环,返回到shell提示符下,需要使用break命令。
1 #!/bin/bash 2 3 while : 4 do 5 echo -n "输入 1 到 3 之间的数字:" 6 read aNum 7 case $aNum in 8 1|2|3) 9 echo "输入的数字为 $aNum" 10 ;; 11 *) 12 echo "输入的数字不是 1 到 3 之间,游戏结束" 13 break 14 ;; 15 esac 16 done
执行以上代码,输出结果:
输入 1 到 3 之间的数字: 3
输入的数字为 3
输入 1 到 3 之间的数字: 6
输入的数字不是 1 到 3 之间,游戏结束
(2) continue 命令
continue 命令与 break 命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。
对上面的例子进行修改:
1 #!/bin/bash 2 3 while : 4 do 5 echo -n "输入 1 到 3 之间的数字: " 6 read aNum 7 case $aNum in 8 1|2|3) 9 echo "输入的数字为 $aNum" 10 ;; 11 *) 12 echo "输入的数字不是 1 到 53 之间" 13 continue 14 echo "游戏结束" 15 ;; 16 esac 17 done
运行代码发现,当输入大于 3 的数字时,该例中的循环不会结束,语句 echo "游戏结束" 不会被执行。