本章内容:
- for循环语句
- until迭代语句使用while语句
- 循环
- 重定向循环的输出
13.1 for命令
for var in list
do
commands
done
在list参数中,需要提供迭代所要用到的一系列值
===
13.1.1 读取列表中的值
for循环假定每个值用空格分割
#!/bin/bash
# testing the for variable after the looping
for test in Alabama Alaska Arizona Arkansas California Colorado
do
echo "The last state we visited was $test"
done
echo "The last state we visited was $test"
test=Connecticut
echo "Wait, now we're visiting $test"
$ ./script/test1
The last state we visited was Alabama
The last state we visited was Alaska
The last state we visited was Arizona
The last state we visited was Arkansas
The last state we visited was California
The last state we visited was Colorado
The last state we visited was Colorado
Wait, now we're visiting Connecticut
===
13.1.2 读取列表中的复杂值
#!/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
单引号会让shell尝试把它之间的值解析成统一个词,所以单引号要做特殊操作
\#!/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
如果单个值中间有空格,则用双引号围起来
===
13.1.3 从变量读取列表
#!/bin/bash
# using a variable to hold the list
list="Alabama Alaska Arizona Arkansas Colorado"
list=$list" Connecticut" #该操作向list中拼接了一个值
for state in $list
do
echo "Have you ever visited $state?"
done
===
13.1.4 从命令中读取值
#!/bin/bash
# reading values from a file
file="states"
for state in $(cat $file)
do
echo "Visit beautiful $state"
done
$ cat states
Alabama
Alaska
Arizona
Arkansas
Colorado
Connecticut
Delaware
Florida
Georgia
states是一个文件
===
13.1.5 更改字段分隔符
造成这个问题的原因是特定的环境变量IFS,叫作内部字段分隔符(internal field separator)。
bash shell会把空格、制表符、换行符当做分隔符
IFS=$'\n' #使得只降换行符当做分隔符
===
13.1.6 用通配符读取目录
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/myprog is a file
/home/rich/test/myscript is a file
/home/rich/test/newdir is a directory
/home/rich/test/newfile is a file
/home/rich/test/newfile2 is a file
/home/rich/test/testdir is a directory
/home/rich/test/testing is a file
/home/rich/test/testprog is a file
/home/rich/test/testprog.c is a file
if语句中,把file用双引号括起来了,防止因为文件名中有空格而出现问题。
13.2 C语言风格的for命令
13.2.1 C语言的for命令
#!/bin/bash
# testing the C-style for loop
for (( i=1; i <= 10; i++ ))
do
echo "The next number is $i"
done
试了一下,for的括号里,几个表达式之间的空格都去掉也是可以解析的
#!/bin/bash
# multiple variables
for (( a=1, b=10; a <= 10; a++, b-- ))
do
echo "$a - $b"
done
多个变量也ok
13.3 while命令
13.3.1 while命令的基本格式
while test command
do
other commands
done
#!/bin/bash
# while command test
var1=10
while [ $var1 -gt 0 ]
do
echo $var1
var1=$[ $var1 - 1 ]
done
上面的空格不能少,否则无法形成有效的判断
===
13.3.2 使用多个测试命令
#!/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
以最后一个测试命令的状态码结束循环
出现死循环的时候用ctrl+C终止
13.4 until明令
until test commands
do
other commands
done
#!/bin/bash
# using the until command
var1=100
until [ $var1 -eq 0 ]
do
echo $var1
var1=$[ $var1 - 25 ]
done
13.5 嵌套循环
#!/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 the loop"
done
done
注意done不要写漏了
13.6 循环处理数据文件
使用嵌套循环+修改IFS值
#!/bin/bash
# changing the IFS value
IFS=$'\n'
for entry in $(cat /etc/passwd)
do
echo "Values in $entry –"
IFS=:
for value in $entry
do
echo " $value"
done
done
13.7 控制循环
break和continue
※ shell中的break可以用来跳出外部循环
break n
n指定了要跳出的循环层级
#!/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
虽然这里只有两层循环,但是写break 3也是可以的(?)
continue命令
也有continue n 的用法
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
13.8 处理循环的输出
可以通过在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
13.9 实例
13.9.1 查找可执行文件
IFS=:
for folder in $PATH
do
echo "$folder:"
for file in $folder/*
do
if [ -x $file ]
then
echo "$file"
fi
done
done
===
13.9.2 创建多个用户账户
#!/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"
$
$ cat users.csv
rich,Richard Blum
christine,Christine Bresnahan
barbara,Barbara Blum
tim,Timothy Bresnahan
$