Linux 命令 & shell 脚本之06(for、while

2020-09-28  本文已影响0人  轻飘飘D

命令格式:

for var in list; do
   commands
done
  1. 读取列表中的值
$ cat test1 
#!/bin/bash 
# basic for command 
for test in Alabama California Colorado; do 
  echo The next state is $test 
done 
$ ./test1 
The next state is Alabama 
The next state is California 
The next state is Colorado

1.1 讀取數組中的值

--------------------------------------------------
for 循環讀取方法
for i in ${variable[@]}; do
    # do something....
done
--------------------------------------------------
[oracle@DB02 myshell]$ cat test_array.sh 
#!/bin/bash 
# basic for command 
#
arr=("aa" "bb" "cc")   
echo "所有的内容如下:" ${arr[@]}   
#数组的下标从0开始
echo "第 2 個 元素值:" ${arr[1]}  
echo "数组的长度方法1:" ${#arr[*]} 
echo "数组的长度方法2:" ${#arr[@]}  

for var in ${arr[@]}; do
   echo "打印的内容:" $var 
done

[oracle@DB02 myshell]$ ./test_array.sh 
所有的内容如下: aa bb cc
第 2 個 元素值: bb
数组的长度方法1: 3
数组的长度方法2: 3
打印的内容: aa
打印的内容: bb
打印的内容: cc

1.2 讀取字典中的值

[oracle@DB02 15]$ cat test_dict.sh 
#!/bin/bash 
#
echo "shell定义字典"
#必须先声明
declare -A dic
#dic=([key1]="value1" [key2]="value2" [key3]="value3")

dic["key1"]="values1"
dic["key3"]="values3"
dic["key5"]="values5"

#打印指定key的value
echo ${dic["key1"]}
#打印所有key值
echo ${!dic[*]}
#打印所有value
echo ${dic[*]}

#遍历key值
for key in $(echo ${!dic[*]}); do
    echo "$key : ${dic[$key]}"
done
---------------------------------------------------------------
[oracle@DB02 15]$ ./test_dict.sh 
shell定义字典
values1
key5 key3 key1
values5 values3 values1
key5 : values5
key3 : values3
key1 : values1

  1. 读取列表中的复杂值(列表值中含单引号)
有两种办法可解决这个问题:
 使用转义字符(反斜线)来将单引号转义;
 使用双引号来定义用到单引号的值

$ cat test2 
#!/bin/bash 
# another example of how not to use the for command 
for test in I don\'t know if "this'll" work; do 
 echo "word : $test" 
done 

$ ./test2 
word : I 
word : don't 
word : know 
word : if 
word : this'll 
word : work
#在第一个有问题的地方添加了反斜线字符来转义don't中的单引号。在第二个有问题的地方将this'll用双引号圈起来。两种方法都能正常辨别出这个值

#for命令用空格来划分列表中的每个值。如果在单独的数据值中有空格,就必须用双引号将这些值圈起来
$ cat test3 
#!/bin/bash 
# an example of how to properly define values 
for test in Nevada "New Hampshire" "New Mexico" "New York"; do 
  echo "Now going to $test" 
done 

$ ./test3 
Now going to Nevada 
Now going to New Hampshire 
Now going to New Mexico 
Now going to New York
  1. 从变量读取列表
$ cat test4 
#!/bin/bash 
# using a variable to hold the list 
list="Alabama Colorado" 
list=$list" Connecticut" 

for state in $list; do 
  echo "Have you ever visited $state?" 
done 

$ ./test4 
Have you ever visited Alabama? 
Have you ever visited Colorado? 
Have you ever visited Connecticut?
  1. 从命令读取值 & 更改字段分隔符
默认情况下,bash shell会将下列字符当作字段分隔符:
 空格
 制表符
 换行符
在处理可能含有空格的数据时可以在shell脚本中临时更改IFS环境变量的值来限制被bash shell当作字段分隔符的字符。
例如,如果你想修改IFS的值,使其只能识别换行符(告诉bash shell在数据值中忽略空格和制表符),那就必须这么做:
IFS=$'\n'

案例1
$ cat test5b 
#!/bin/bash 
# reading values from a file 
file="states" 
IFS=$'\n' 
for state in $(cat $file); do 
  echo "Visit beautiful $state" 
done

$ cat states 
Alabama 
Colorado 
Delaware 
New York
North Carolina

$ ./test5b 
266 第 13 章 更多的结构化命令
Visit beautiful Alabama 
Visit beautiful Colorado 
Visit beautiful Delaware 
Visit beautiful New York 
Visit beautiful North Carolina

你要做的就是将IFS的值设为冒号。
IFS=: 
如果要指定多个IFS字符,只要将它们在赋值行串起来就行。
IFS=$'\n':;" 
这个赋值会将换行符、冒号、分号和双引号作为字段分隔符
  1. 用通配符读取目录
应该将$file变量用双引号圈起来。如果不这么做,遇到含有空格的目录名或文件名时就会有错误产生
$ cat test6 
#!/bin/bash 
# iterate through all the files in a directory 

for file in /home/rich/test/*; do 
 if [ -d "$file" ]; then 
   echo "$file is a directory" 
 elif [ -f "$file" ]; then 
   echo "$file is a file" 
 fi 
done 

$ ./test6 
/home/rich/test/dir1 is a directory 
/home/rich/test/myprog.c is a file 
/home/rich/test/testprog.c is a file

6.bash中C语言风格的for循环

基本格式:
for (( variable assignment ; condition ; iteration process ))
do
  ...
done 

or 
for (( variable assignment ; condition ; iteration process )); do
  ...
done 

案例
$ cat test8 
#!/bin/bash 
# testing the C-style for loop 
for (( i=1; i <= 5; i++ )) 
do 
  echo "The next number is $i" 
done 

$ ./test8 
The next number is 1 
The next number is 2 
The next number is 3 
The next number is 4 
The next number is 5

使用多个变量:
可以为每个变量定义不同的迭代过程。尽管可以使用多个变量,但你只能在for循环中定义一种条件
$ cat test9 
270 第 13 章 更多的结构化命令
#!/bin/bash 
# multiple variables 
for (( a=1, b=10; a <= 10; a++, b-- )); do 
   echo "$a - $b" 
done 

$ ./test9 
1 - 10 
2 - 9 
...
9 - 2 
10 - 1
  1. while 命令
while命令的格式是:
while test command 
do 
 other commands 
done

$ cat test10 
#!/bin/bash 
# while command test 
var1=10 

while [ $var1 -gt 0 ] 
do 
  echo $var1 
  var1=$[ $var1 - 1 ] 
done 

$ ./test10 
10 
9 
...
2 
1 
  1. until 命令
until命令的格式如下。
until test commands 
do 
  other commands 
done

案例:
$ cat test12 
#!/bin/bash 
# using the until command 
var1=100 
until [ $var1 -eq 0 ] 
do 
  echo $var1 
  var1=$[ $var1 - 25 ] 
done 

$ ./test12 
100 
75 
50 
25
  1. 案例-循环处理文件数据
典型的例子是处理/etc/passwd文件中的数据。这要求你逐行遍历/etc/passwd文件,
并将IFS变量的值改成冒号,这样就能分隔开每行中的各个数据段了

#!/bin/bash 
# changing the IFS value 
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

在运行这个脚本时,你会得到如下输出。
Values in rich:x:501:501:Rich Blum:/home/rich:/bin/bash - 
 rich 
 501 
 501 
 Rich Blum 
 /home/rich 
 /bin/bash 
 Values in katie:x:502:502:Katie Blum:/home/katie:/bin/bash - 
 katie 
 x 
 506 
 509 
 Katie Blum 
 /home/katie 
 /bin/bash
  1. break 命令 (用break命令来退出任意类型的循环,包括while和until循环)
    10.1 跳出单个循环
$ cat test17 
#!/bin/bash 
# breaking out of a for loop 
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"

 ./test17 
Iteration number: 1 
Iteration number: 2 
Iteration number: 3 
Iteration number: 4 
The for loop is completed

$ cat test18 
#!/bin/bash 
# breaking out of a while loop 
var1=1 
while [ $var1 -lt 10 ] 
do 
 if [ $var1 -eq 5 ] 
 then 
     break 
 fi 
 echo "Iteration: $var1" 
 var1=$[ $var1 + 1 ] 
done 
echo "The while loop is completed" 

$ ./test18 
Iteration: 1 
Iteration: 2 
Iteration: 3 
Iteration: 4 
The while loop is completed

10.2 跳出内部循环

$ cat test19 
#!/bin/bash 
# breaking out of an inner loop 
for (( a = 1; a < 3; 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 

$ ./test19 
Outer loop: 1 
 Inner loop: 1 
 Inner loop: 2 
 Inner loop: 3 
 Inner loop: 4 
Outer loop: 2 
 Inner loop: 1 
 Inner loop: 2 
 Inner loop: 3 
 Inner loop: 4 

10.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 3 ] 
   then 
     break 2 
   fi 
   echo " Inner loop: $b" 
 done 
done 

$ ./test20 
Outer loop: 1 
 Inner loop: 1 
 Inner loop: 2 
 Inner loop: 3
  1. continue 命令
$ 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

和break命令一样,continue命令也允许通过命令行参数指定要继续执行哪一级循环:
continue n
其中n定义了要继续的循环层级。下面是继续外部for循环的一个例子:

$ cat test22 
#!/bin/bash 
# continuing an outer loop 
for (( a = 1; a <= 5; a++ )); do 
   echo "Iteration $a:" 
   for (( b = 1; b < 3; b++ )); do 
     if [ $a -gt 2 ] && [ $a -lt 4 ] 
     then 
       continue 2 
     fi 
     var3=$[ $a * $b ] 
     echo " The result of $a * $b is $var3" 
   done 
done 

$ ./test22 
Iteration 1: 
 The result of 1 * 1 is 1 
 The result of 1 * 2 is 2 
Iteration 2: 
 The result of 2 * 1 is 2 
 The result of 2 * 2 is 4 
Iteration 3: 
Iteration 4: 
 The result of 4 * 1 is 4 
 The result of 4 * 2 is 8 
Iteration 5: 
 The result of 5 * 1 is 5 
 The result of 5 * 2 is 10
  1. 对循环的输出使用管道或进行重定向
$ cat test23 
#!/bin/bash
# redirecting the for output to a file 
for (( a = 1; a < 6; a++ )); do 
  echo "The number is $a" 
done > test23.txt 
echo "The command is finished." 

$ ./test23 
The command is finished. 
$ cat test23.txt 
The number is 1 
The number is 2 
The number is 3 
The number is 4 
The number is 5 

$ cat test24 
#!/bin/bash 
# piping a loop to another command 
for state in "North Dakota" Connecticut Alabama; 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 
North Dakota is the next place to go 
This completes our travels
上一篇 下一篇

猜你喜欢

热点阅读