有三种内置循环语句命令for, while, until

for

for var in word1 word2 ... wordn
do
  command
  command
  ...
done

for循环中,word[1-n]泪飙会依次赋值给变量var,每次赋值后执行一次dodone之间的语句。
示例:

for i in 1 2 3
do
  echo $1
done

输出结果

1
2
3

for中的参数列表支持文件名替代, 所以可以有如下语句

for file in memo[1-4]   # 等价于 for file in memo1 memo2 memo3 memo4
do
done
for file in *
do
done
for file in $(cat filelist) # 文件filelist中保存有一些文件名
do
done

在命令文件中接受参数时,$*代表所有参数,所以可以使用for var in $*遍历所有参数

$@

现有如下程序args

for arg in $*
do
  echo $arg
done

则在命令行运行args 'a b' c得到的结果为:

a
b
c

这是因为在$*替换为参数时'a b'被拆分成了a b两个参数。这时如果使用"$@"代替$*即可。 如果不加"",则$@$*没有区别
args

for arg in "$@"
do
  echo $arg
done

for without the list

for var
do
  command
done

上面的语句等效于

for var in "$@"
do
  command
done

while

while [[ condition ]]; do
  #statements
done

首先判定conditionexit status,如果为0(true)则执行一次dodone之间的语句。
执行完之后再次判定,直到condition判定为false为止
示例

while [[ "$#" -ne 0 ]]; do
  echo "$1"
  shift
done

until

until [[ condition ]]; do
  #statements
done

while不同的是,只有当condition返回非0值(false)时才会执行循环体
while一用,循环体中的内容也可能一次都不会被执行

sleep n  # 使程序暂停n秒

more on loops

breaking out of a loop

break

示例

while true; do
  cmd=$(getcmd)

  if [ "$cmd" = quit]; then
    break
  else
    processcmd "$cmd"
  fi
done

如果循环里嵌套着循环,则可以使用break n语句同时跳除n层循环

skipping the remaining commands in a loop

continue
continue n

executing a loop in the background

done后面添加&即可

I/O redirection on a loop

done后面使用>运算符可以将循环中的所有结果都导入文件中
如果循环体中某跳语句也使用了>进行输出转换,则其自身的转换会覆盖循环的转换

  • > /dev/tty可以将结果输出到终端显示
  • > /dev/null不输出结果
  • 2> filestandard error输出到文件中
  • 1>&2将结果输出到终端,即使它被导向其它文件或通道

piping data into and out of a loop

将循环当成一个整体然后使用|

typing a loop on one line

for i in 1 2 3; do echo $i; done

注意,在do后面时没有;
同样也可以对if使用;将其写成一行,注意thenelse后面不加;

getopts

getopts options variable

该命令常被用与检测在命令行输入的参数。 getopts ab:c variable则表示只接受-a, -b-c三个配置参数,且-b后需要有一个参数表示其值

while [ getopts mt: option ]; do
  case "$option" in
    m) command;;
    t) var=$OPTARG;;
    \?) echo "Usage: waitfor [-m] [-t n] user"
        exit 1;;
  esac
done

命令行中的输入第一个参数首先进行getopts运算,如果参数以-开头且后跟的字母在options中(这里即为mt), 则将后跟的字母保存在变量option中(变量名随意),并将exit status0返回。下一次循环时则判定第二个参数
如果-后跟的字母不在options之中,则将?保存在变量option中,并将exit status0返回
如果参数不是以-开头,则getopts直接返回一个非0的exit status
由于mt:t后跟了一个:,所以如果getopts检测到参数为-t则其会继续检测该参数后面一个参数, 如果没有或者以-开头,则将?赋值给变量option,并想standard error中输出一条错误;否则将后面跟着的参数 赋值给变量OPTARG

还有一个特殊变量OPTIND,其初始值为1,每次迭代完则自动加1。 所以$OPTIND的值比以-开头的参数个数大1(不包括赋值给OPTARG的参数)。 可以以此来判定除以-开头的参数外还有没有其它参数