在日常工作中,学会使用shell编程,可以在很大程度上替代手工重复性质的工作,提高工作效率。从这点上来说,了解shell中循环的写法非常关键。下面介绍shell中的while循环和for循环。
1、两种循环基本写法
常见的while和for循环的写法,大概有如下几种:
(1) 通过输入重定向到while循环
while read line
do
echo $line
done < file(待读取的文件)
(2) 通过cat命令输出重定向到while循环
cat file(待读取的文件) | while read line
do
echo $line
done
(3) for循环读取命令输出
for line in `cat file(待读取的文件)`
do
echo $line
done
2、两种循环的区别
按照我的理解,准确的说,上面例子中while和for循环的区别在于:while循环会将每行的内容读入到line变量;for循环中,将读入的内容以IFS(shell中的环境变量,Internal Field Seperator,字段分隔符)为界分隔,然后将各个分隔开的内容,逐一读入变量line。本质上说,for循环读取的是字段,只不过可以设置IFS为\n
这样能够逐行读取。
为了方便测试,我们用echo命令来实现多行文字的输出。其中,echo命令的-e
选项,意思就是可以识别转义字符能够输出行分隔符。如下例:
$ echo -e "a 12\nb 10"
a 12
b 10
$
(1) while逐行读文件
$ echo -e "a 12\nb 10" | while read line
> do
> echo $line
> done
a 12
b 10
$
(2) for循环的默认行为
$ for line in `echo -e "a 12\nb 10"`
> do
> echo $line
> done
a
12
b
10
$
(3) 通过改变IFS实现for循环按行读入
$ IFS=$'\n'
$ for line in `echo -e "a 12\nb 10"`
> do
> echo $line
> done
a 12
b 10
$
除了上面常见循环的写法,while循环在逐行读入的同时,还能够根据IFS将整行的内容分隔成多个字段,依次赋值给read后跟的变量名。如果变量数目多余字段的实际个数,少的那些变量值为空;如果变量的数目少于字段实际个数,最后一个变量对所有后面的字段照单全收。下面是一个例子:
$ echo -e "Tom 13\nLily 10 120cm\nJohn" | while read name age
> do
> echo "${name}: ${age}"
> done
Tom: 13
Lily: 10 120cm
John:
$
3、一个简单的shell循环应用
假定有这样一个场景,需要在一个目录中,查找好多关键词。如果用shell搞定,我们就需要先将待搜索的关键词写入一个文件,比如keyword.txt,每行一个关键词。然后,写一个脚本读这个文件,取出每个关键词,然后用grep命令查找。下面是一个参考脚本的例子:
keyword_file='keyword.txt'
search_dir='/xx/path/'
result_file=result.txt
echo "Results:" | tee $result_file
cat $keyword_file | while read keyword
do
echo "${keyword}:" | tee -a $result_file
#word match, recursively search in directory and sub directory. only .java file will be searched. case insensitive. -l means only list file name
grep -irw --include="*.java" "$keyword" "$search_dir" -l | tee -a $result_file
echo "" | tee -a $result_file
done
运行结果如下:
$ cat keyword.txt
Polymerize
SortMeta
DataTube
$ sh search.sh
Results:
Polymerize:
/xx/path//src/com/poly/merge/test/TestMergeSortDesc.java
/xx/path//src/com/poly/merge/test/TestMergeSortDescMultiSort.java
/xx/path//src/com/poly/merge/basic/Polymerize.java
SortMeta:
/xx/path//src/com/poly/merge/test/TestMergeSort.java
/xx/path//src/com/poly/merge/test/TestMergeSort16.java
DataTube:
/xx/path//UnitTest/com/poly/merge/basic/PolymerizeTest.java
/xx/path//src/com/poly/merge/test/TestMergeSort.java
/xx/path//src/com/poly/merge/test/DataTubeImp16.java
/xx/path//src/com/poly/merge/basic/Polymerize.java
/xx/path//src/com/poly/merge/basic/DataTube.java
$
网友评论