Shell while循环语句中的陷阱

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

会是家庭电脑的主流操作系统。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容