Cai*_*ife 20 bash shell file-io parsing
我通常使用read命令逐行读取shell脚本的输入文件.如果未在输入文件blah.txt中的最后一行末尾插入新行,则下面的示例代码会产生错误的结果.
#!/bin/sh
while read line
do
echo $line
done <blah.txt
Run Code Online (Sandbox Code Playgroud)
因此,如果输入文件读取类似于 -
One
Two
Three
Four
Run Code Online (Sandbox Code Playgroud)
我四点后没有回复,脚本无法读取最后一行,并打印出来
One
Two
Three
Run Code Online (Sandbox Code Playgroud)
现在,如果我在四个之后留下一个额外的空白行,比如,
One
Two
Three
Four
//blank line
Run Code Online (Sandbox Code Playgroud)
输出打印所有行,包括四行.但是,当我使用cat命令读取一行时,情况并非如此; 包括最后一行在内的所有行都打印出来,而不必在末尾添加额外的空白行.
有人知道为什么会这样吗?我创建的脚本主要由其他人运行,因此没有必要在每个输入文件的末尾添加额外的空行.
我一直试图解决这个问题; 如果你有任何解决方案我会很感激(当然,cat命令是一个,但我想知道阅读不起作用的原因).
ric*_*ici 21
read读取直到找到换行符或文件结尾,并在遇到文件结尾时返回非零退出代码.所以它很可能同时读取一行并返回非零退出代码.
因此,如果输入可能未被换行终止,则以下代码不安全:
while read LINE; do
# do something with LINE
done
Run Code Online (Sandbox Code Playgroud)
因为while不会在最后一行执行该主体.
从技术上讲,未以换行符终止的文件不是文本文件,文本工具可能会以奇怪的方式在这样的文件上失败.但是,我总是不愿意回避这个解释.
解决问题的一种方法是测试读取的内容是否为非空(-n):
while read -r LINE || [[ -n $LINE ]]; do
# do something with LINE
done
Run Code Online (Sandbox Code Playgroud)
其他解决方案包括使用mapfile将文件读入数组,通过某些实用程序管理文件,保证正确终止最后一行(grep .例如,如果您不想处理空行),或进行迭代处理使用类似的工具awk(这通常是我的偏好).
注意内置-r几乎肯定需要read; 它导致read不重新解释\输入中的序列.
小智 8
DONE=false
until $DONE
do
read line || DONE=true
echo $line
done < blah.txt
Run Code Online (Sandbox Code Playgroud)
如果文件末尾没有换行符,如何使用`read read`(Bash)读取文件中的最后一行?
像这样使用while循环:
while IFS= read -r line || [ -n "$line" ]; do
echo "$line"
done <file
Run Code Online (Sandbox Code Playgroud)
或者使用grepwhile循环:
while IFS= read -r line; do
echo "$line"
done < <(grep "" file)
Run Code Online (Sandbox Code Playgroud)
使用grep .代替grep ""将跳过空行。
注意:
使用IFS=可使所有行缩进保持不变。
结尾没有换行符的文件不是标准的UNIX文本文件。