文章目录
1.for命令
bash shell提供了for命令,允许创建一个遍历一系列值的循环。
每次迭代都使用其中一个值来执行已定义好的一组命令。
bash shell中for命令的基本格式如下:
for var in list
do
commands
done
1.1 读取列表中的值
eg:
for test in a,b,c,d,e
do
echo $test
done
#a,b,c,d,e
1.2 读取列表中的复杂值
Q:如何算列表中的复杂值?
A:通常有两种情况:
- shell看到了列表值中的单引号并尝试使用它们来定义一个单独的数据值。
- for循环假定每个值都是用空格分割的。
Q:如何解决上述两种情况?
A:
对于第一种:可以采用转义字符(反斜杠)来将单引号转义或者使用双引号来定义用到单引号的值。
eg:
for test in I don't know if this'll work
do
echo $test
done
#I
#dont know if thisll
#work
for test in I don\'t know if "this'll" work
do
echo $test
done
#I
#don't
#know
#if
#this'll
#work
对于第二种:for命令用空格来划分列表中的每个值。如果在单独的数据值中有空格,就必须用双引号将这些值圈起来。
eg:
for test in I come form Shanghai University
do
echo $test
done
#I
#come
#form
#Shanghai
#University
for test in I come form "Shanghai University"
do
echo $test
done
#I
#come
#form
#Shanghai University
1.3 从变量读取列表
ps:向变量中存储的已有文本字符串尾部添加文本的一个常用方法。
eg:
list="a b c d e"
list=$list" f" #向变量list中存储的已有文本字符串尾部添加字符f
for test in $list
do
echo $test
done
#a
#b
#c
#d
#e
#f
1.4 从命令读取值
生成列表中所需值的另外一个途径就是使用命令的输出。可以用命令替换来执行任何能产生输出的命令,然后在for命令中使用该命令的输出。
eg:
ls > file
for test in $(cat file)
do
echo "the next file is $test"
done
#the next file is 1
#the next file is bb
#the next file is file
#the next file is myshell
#the next file is z
1.5 更改字符分隔符–IFS(特殊的环境变量)
默认情况下,bash shell 会将下列字符当作字符分隔符。这可能导致原本是同一单词被拆分成两个词。
- 空格
- 制表符
- 换行符
Q:如何解决上述分隔符导致的问题?
A:可以在shell脚本中临时更改IFS环境变量的值来限制被bash shell当作字段分隔符的字符。
eg:IFS=$'\n'
。这样即可识别换行符了。
eg:
file="states"
IFS=$'\n'
for state in $(cat $file)
do
echo "Visit beautiful $state"
done
#Visit beautiful Florida
#Visit beautiful Georgia
#Visit beautiful New York
#Visit beautiful New Hampshire
#Visit beautiful North Carolina
notice:
- 在处理代码量较大的脚本时,可能在一个地方需要修改IFS的值,然后忽略这次修改,在
脚本的其他地方继续沿用IFS的默认值。一个可参考的安全实践是在改变IFS之前保存原
来的IFS值,之后再恢复它。
这种技术可以这样实现以保证在脚本的后续操作中使用的是IFS的默认值:IFS.OLD=$IFS IFS=$'\n' #在代码中使用新的IFS值 IFS=$IFS.OLD
- 如果要指定多个IFS字符,只要将它们在赋值行串起来就行。eg:
IFS=$'\n':;'"
- 如何使用IFS字符解析数据没有任何限制。
1.6 用通配符读取目录
可以用for命令来自动遍历目录中的文件。
文件扩展匹配是生成匹配指定通配符的文件名或路径名的过程。
notice:在Linux中,目录名和文件名中包含空格是合法的。要适应这种情况,应该将$file
用双引号圈起来,否则,遇到含有空格的目录名和文件名就会产生错误。
eg:
for file in ./*
do
if [ -d "$file" ] # [] 里面双面都要有空格
then
echo "$file" "is dir"
elif [ -f "$file" ]
then
echo "$file" "is file"
fi
done
#./1 is file
#./bb is file
#./file is file
#./myshell is file
#./z is file
2.C语言风格for命令
bash shell 的 for命令也提供了C语言的风格使用方式。
即在C语言中,for循环通常定义一个变量,然后这个变量会在每次迭代时自动改变。通常程序员会将这个变量用作计数器,并在每次迭代中让计数器加一或者减一。
为了专心学习shell,C语言风格这里的例程不贴了,以免新手混淆。有兴趣的自行查阅书籍或者资料。
2.1 C语言的for命令
bash shell 中 C语言的for命令格式如下:
for (( variable assignment ; condition ; iteration process ))
C语言风格的for命令格式看起来有些部分并没有遵循bash shell标准的for命令。
- 变量赋值可以有空格
- 条件中的变量不以美元符开头
- 迭代过程的算式未用expr命令格式。
2.2 使用多个变量
C语言风格的for命令也允许为迭代使用多个变量。循环会单独处理每个变量,你可以为每个变量定义不同的迭代过程。尽管可以使用多个变量,但你只能在for循环中定义一种条件。
3.while命令
3.1 while的基本格式
while的基本格式如下:
while test command
do
other commands
done
while命令的关键在于所指定的test command的退出状态码必须随着循环中运行的命令而改变。
如果退出状态码不发生变化, while循环就将一直不停地进行下去。
eg:
var=5
while [ $var -gt 0 ] # var 是否大于0
do
echo $var
var=$[ $var - 1]
done
#5
#4
#3
#2
#1
3.2 使用多个测试命令
while命令允许在while语句行定义多个测试命令。
只有最后一个测试命令的退出状态码会被用来决定什么时候结束循环。
使用多个测试命令需要注意如下:
- 在含有多个命令的while语句中,在每次迭代中所有测试命令都会被执行,包括测试命令失败的最后一次迭代。
- 留意如何指定多个测试命令,即每个测试命令都必须出现在单独的一行上。
eg:
var=5
while echo $var
[ $var -ge 0 ] # var 是否大于或等于0
do
echo "loop"
var=$[ $var - 1]
done
#5
#loop
#4
#loop
#3
#loop
#2
#loop
#1
#loop
#0
#loop
#-1
4.until命令
until命令格式如下:
until test commands
do
other commands
done
test commands 是一个通常返回非零退出状态码的测试命令;
Q:什么时候停止?
A:当test commands返回0退出状态码。
eg:
var=5
until [ $var -eq 0 ]
do
echo $var
var=$[ $var - 1 ]
done
#5
#4
#3
#2
#1
notice:多条测试命令的要求同while测试命令。
5.嵌套循环
Q:何为嵌套循环(nested loop)?
A:循环语句可以在循环内使用任意类型的命令,包括其他循环命令,即为嵌套循环。
notice:
- 在使用嵌套循环时,你是在迭代中使用迭代,与命令运行的次数是乘积关系。
- bash shell知道当第一个done命令执行时是指内部循环而非外部循环。
ps:嵌套循环的理念和其他语言是一致的。
6.循环处理文件数据–嵌套循环+修改IFS环境变量
Q:如何遍历存储在文件中的数据?也就是如何循环处理文件数据
A:使用嵌套循环+修改IFS环境变量。
eg:
IFS.OLD=$IFS
IFS=$'\n'
for entry in $(cat /etc/passwd)
do
echo "Vaule in $entry -"
IFS=:
for value in $enrty
do
echo " $value"
done
done
#Values in katie:x:502:502:Katie Blum:/home/katie:/bin/bash -
# katie
# x
# 506
# 509
# Katie Blum
# /home/katie
# /bin/bash
#此处eg是用的书上的,笔者自己测试的总是报IFS.OLD=: 未找到命令,不知为何,知道的大佬还请评论区指教。感谢!!
7.控制循环
7.1 break命令
break命令是退出循环的一个简单方法。
可以用break命令来退出任意类型的循环,包括while和until循环。
break命令接受单个命令行参数值:break n
:n是代表的循环层级。
7.2 continue命令
continue命令可以提前中止某次循环中的命令,但并不会完全终止整个循环。
可以在循环内部设置shell不执行命令的条件。
8.处理循环的输出–done结束添加一个处理命令
在shell脚本中,可以对循环的输出使用管道或进行重定向。通过在done命令之后添加一个处理命令来实现。
采用3.1的例子。
eg:
var=5
while [ $var -gt 0 ] # var 是否大于0
do
echo $var
var=$[ $var - 1]
done > 3_1_while.log
cat 3_1_while.log
#5
#4
#3
#2
#1
申明:文中没特殊注明,图皆来自Linux命令行与shell脚本编程大全<第三版>。