shell 更多的结构化命令

更多的结构化命令


for命令

读取列表中的值

for 循环假定各个值之间是以空格分隔的

  • 使用转义字符(反斜线)将单引号转义
  • 使用双引号来定义含有单引号的值
#!/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

# 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

从变量中读取值列表

#!/bin/bash
# using a variable to hold the list
 
list="Alabama Alaska Arizona Arkansas Colorado"
list=$list" Connecticut"
 
for state in $list
do
   echo "Have you ever visited $state?"
done

从命令中读取值列表

#!/bin/bash
# reading values from a file
 
file="states"
 
for state in $(cat $file)
do
   echo "Visit beautiful $state"
done

更改字段分隔符

造成这个问题的原因是特殊的环境变量 IFS(internal field separator,内部字段分隔符)。IFS 环境变量定义了 bash shell 用作字段分隔符的一系列字符。在默认情况下,bash shell 会将下列字 符视为字段分隔符。

  • 空格
  • 制表符
  • 换行符
#!/bin/bash
# reading values from a file
 
file="states"
 
IFS=$'\n'
for state in $(cat $file)
do
   echo "Visit beautiful $state"
done

在处理代码量较大的脚本时,可能在一个地方需要修改 IFS 的值,然后再将其恢复原 状,而脚本的其他地方则继续沿用 IFS 的默认值。一种安全的做法是在修改 IFS 之前保 存原来的 IFS 值,之后再恢复它。
这种技术可以像下面这样来实现:

IFS.OLD= I F S I F S = IFS IFS= IFSIFS=‘\n’ <在代码中使用新的 IFS 值> IFS=$IFS.OLD

这就保证了在脚本的后续操作中使用的是 IFS 的默认值。

使用通配符读取目录

#!/bin/bash
# iterating through multiple directories
 
for file in /home/rich/.b* /home/rich/badtest
do
   if [ -d "$file" ]
   then
      echo "$file is a directory"
   elif [ -f "$file" ]
   then
      echo "$file is a file"
   else
     echo "$file doesn't exist"
   fi
done

c语言风格

注意,有些地方与 bash shell 标准的 for 命令并不一致。

  • 变量赋值可以有空格。
  • 迭代条件中的变量不以美元符号开头。
  • 迭代过程的算式不使用 expr 命令格式。
#!/bin/bash
# testing the C-style for loop
 
for (( i=1; i <= 10; i++ ))
do
   echo "The next number is $i"
done

# multiple variables
 
for (( a=1, b=10; a <= 10; a++, b-- ))
do
   echo "$a - $b"
done

while命令

#!/bin/bash
# while command test
 
var1=10
while [ $var1 -gt 0 ]
do
   echo $var1
   var1=$[ $var1 - 1 ]
done

while 命令允许在 while 语句行定义多个测试命令。只有最后一个测试命令的退出状态码 会被用于决定是否结束循环。如果你不小心,这可能会导致一些有意思的结果。

#!/bin/bash
# testing a multicommand while loop
 
var1=10

while echo $var1
      [ $var1 -ge 0 ]
do
   echo "This is inside the loop"
   var1=$[ $var1 - 1 ]
done

until命令

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

嵌套循环

#!/bin/bash
# nesting for loops
 
for (( a = 1; a <= 3; a++ ))
do
   echo "Starting loop $a:"
   for (( b = 1; b <= 3; b++ ))
   do
      echo "   Inside loop: $b"
   done
done

# placing a for loop inside a while loop
var1=5
 
while [ $var1 -ge 0 ]
do
   echo "Outer loop: $var1"
   for (( var2 = 1; $var2 < 3; var2++ ))
   do
      var3=$[ $var1 * $var2 ]
      echo "  Inner loop: $var1 * $var2 = $var3"
   done
   var1=$[ $var1 - 1 ]
done


# using until and while loops 
var1=3
 
until [ $var1 -eq 0 ]
do
   echo "Outer loop: $var1"
   var2=1
   while [ $var2 -lt 5 ]
   do
      var3=$(echo "scale=4; $var1 / $var2" | bc)
      echo "   Inner loop: $var1 / $var2 = $var3"
      var2=$[ $var2 + 1 ]
   done
   var1=$[ $var1 - 1 ]
done

循环控制

你可能认为循环一旦启动,在结束之前就哪都去不了了。事实并非如此。有两个命令可以控 制循环的结束时机。

  • break 命令
  • continue 命令

break

跳出单个循环

#!/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"

# 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"

跳出内层循环

#!/bin/bash
# breaking out of an inner loop
 
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

跳出外层循环

#!/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

continue

#!/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

# 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

处理循环的输出

#!/bin/bash
# redirecting the for output to a file
for (( a = 1; a < 10; a++ ))
do
   echo "The number is $a"
done > test23.txt
echo "The command is finished."

# 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"

实战

查找可执行文件

#!/bin/bash
# finding files in the PATH

IFS=:
for folder in $PATH
do
   echo "$folder:"
   for file in $folder/*
   do
      if [ -x $file ]
      then
         echo "   $file"
      fi
   done
done

创建多个用户账户

#!/bin/bash
# process new user accounts

input="users.csv"
while IFS=',' read -r userid name
do
  echo "adding $userid"
  useradd -c "$name" -m $userid
done < "$input"

小结

循环是编程不可或缺的一部分。bash shell 提供了 3 种可用于脚本中的循环命令。

for 命令允许遍历一系列的值,无论是在命令行中提供的,还是包含在变量中的,或是通过 文件名通配符匹配获得的文件名和目录名。

while 命令提供了基于命令(使用普通命令或 test 命令)的循环方式。只有在命令(或条 件)产生退出状态码 0 时,while 循环才会继续迭代指定的一组命令。

until 命令提供了迭代命令的另一种方式,但它的迭代建立在命令(或条件)产生非 0 退出 状态码的基础上。这个特性允许你设置一个迭代结束前都必须满足的条件。

你可以在 shell 脚本中组合多种循环方式,生成多层循环。bash shell 提供了 continue 命令 和 break 命令,允许根据循环内的不同值改变循环的正常流程。

bash shell 还允许使用标准的命令重定向和管道来改变循环的输出。你可以将循环的输出重 定向至文件或是通过管道将循环的输出传给另一个命令。这就为控制 shell 脚本执行提供了丰富 的功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值