1.while循环中对变量赋值无效
我们经常使用while来循环读取文件的每一行,并用文件中的数据对变量赋值,典型写法如下
#!/bin/bash
value=0
echo "value=$value"
cat data.txt | while read line
do
value=$line
done
echo "value=$value"
结果显示两次value打印都是0,循环中的赋值没有起作用。问题出在这种while写法上,cat file | while read 的意思是:使用 cat 命令查看文件,通过管道将结果传送给包含 read 命令的 while 命令,会每次读取文件中的一行文本,传给read后的参数,参数可以为多个,默认以空格分隔,当文件中没有可读取的文本时,read 命令将以非零状态退出。这就意味着while循环中的程序实际上是在一个子进程中执行的,当前进程通过管道将文件内容传递到子进程。循环体中的value并非是外部定义的value,在循环体中对value赋值自然也不能改变外部value的值。
解决方法是换一种读文件的方法,将循环体放到当前进程中执行。
while read line
do
value=$line
done < data.txt
echo $value
cat file | while read 是一种很不友好的写法,虽然最常用,但是效果最差。推荐使用以上<data.txt的读文件方法。
2.while循环读取不到文件最后一行
用上述cat | while写法读文件时还可能碰见另一个问题:读不到文件的最后一行。如data.txt文件的内容如下
111
222
333
用上述cat | while写法则可能只会读到222,最后一行333被忽视了。上文已经说到while如果判断没有可读取的文本时就会退出,while判断是否到达文件末尾是识别文件结束符EOF。文件最后一行之后如果没有换行符\n,则read读取最后一行时遇到EOF,循环即终止。此时虽在内存有最后一行,但程序已经没有机会再处理此行内容。
知道原因了就可以解决这个问题,权宜之计是在最后一行的后面再换个行。治标的方法是用dos2unix将文件格式转换为Unix,因为缺少换行符一般是由于Windows文件传到Linux没有转换格式。
dos2unix data.txt
Linux命令行真的是宝藏,功能丰富,用法多样。如果Linux的生态圈能够更发达一点,说不定以后Linux
会是家庭电脑的主流操作系统。