假设我有以下Bash脚本:
while read SCRIPT_SOURCE_LINE; do
echo "$SCRIPT_SOURCE_LINE"
done
我注意到,对于最后没有换行的文件,这将有效地跳过最后一行 .
我一直在寻找解决方案and found this:
当读取到达文件结尾而不是行尾时,它会读入数据并将其分配给变量,但它会以非零状态退出 . 如果您的循环是“在读取时构建的;执行操作;完成所以不要直接测试读取退出状态,测试一个标志,并让读取命令在循环体内设置该标志 . 这样无论读取退出状态如何,整个循环体运行,因为read只是循环中的命令列表之一,而不是任何其他循环中的命令列表,而不是循环是否会运行的决定因素.DONE = false
直到$ DONE;做
读|| DONE = TRUE
#process $ REPLY here
完成</path/to/file.in
如何重写此解决方案使其行为与我之前的 while
循环完全相同,即没有硬编码输入文件的位置?
7 回答
在你的第一个例子中,我假设你正在读取stdin . 要对第二个代码块执行相同操作,您只需删除重定向并回显$ REPLY:
我使用以下构造:
除了输入中的空字符外,它几乎可以使用任何东西:
以空行开头或结尾的文件
以空格开头或结尾的行
没有终止换行符的文件
使用带有while循环的
grep
:使用
grep .
而不是grep ""
将跳过空行 .注意:
使用
IFS=
保持任何行缩进不变 .You should almost always use the -r option with read.
末尾没有换行符的文件不是标准的unix文本文件 .
而不是阅读,尝试使用像T恤,猫等GNU Coreutils .
来自stdin
从文件
这里的基本问题是
read
会在遇到EOF时返回errorlevel 1,即使它仍然正确地提供变量 .所以你可以在你的循环中立即使用
read
的errorlevel,另外,不会解析最后的数据 . 但你可以这样做:如果你想要一个非常可靠的方法来解析你的行,你应该使用:
请记住:
NUL字符将被忽略
如果你坚持使用
echo
来模仿cat
的行为你需要在检测到EOF时强制echo -n
(你可以使用条件[ "$eof" == true ]
)@Netcoder的答案很好,这种优化消除了虚假的空白行,也允许最后一行没有换行,如果原来是这样的话 .
我使用了这个的变体来创建2个函数,以允许包含'['的文本管道以保持grep快乐 . (你可以添加其他翻译)
(传递 - 因为$ 1启用管道,否则只是翻译参数)
这是我一直在使用的模式:
这是有效的,因为即使
while
循环从read
出口"test"以非零代码结束,read
仍然填充内置变量$REPLY
(或您选择用read
分配的任何变量) .