在日常工作中, 学会使用 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
- $
参考资料
Shell 编程中 while 与 for 的区别及用法详解 https://www.jb51.net/article/79002.htm
来源: http://www.jianshu.com/p/2ede30dcfc6f