Bash 如果存在’;文件末尾没有换行符吗?
假设我有以下Bash脚本:Bash 如果存在’;文件末尾没有换行符吗?,bash,newline,eof,Bash,Newline,Eof,假设我有以下Bash脚本: while read SCRIPT_SOURCE_LINE; do echo "$SCRIPT_SOURCE_LINE" done 我注意到,对于结尾没有换行符的文件,这将有效地跳过最后一行 我四处寻找解决方案: 当读取到达文件末尾时 在行尾,它在 数据并将其分配给变量, 但它以非零状态退出。 如果您的循环是“while”构造的 阅读;做事;完成 因此,与其测试读取出口 直接状态,测试一个标志,并具有 read命令从中设置该标志 在环体内。那样 无论读取退出状态
while read SCRIPT_SOURCE_LINE; do
echo "$SCRIPT_SOURCE_LINE"
done
我注意到,对于结尾没有换行符的文件,这将有效地跳过最后一行
我四处寻找解决方案:
当读取到达文件末尾时
在行尾,它在
数据并将其分配给变量,
但它以非零状态退出。
如果您的循环是“while”构造的
阅读;做事;完成
因此,与其测试读取出口
直接状态,测试一个标志,并具有
read命令从中设置该标志
在环体内。那样
无论读取退出状态如何
整个循环体运行,因为读取
只是命令列表中的一个
像其他人一样,在循环中,而不是
决定循环是否运行的因素
跑吧
DONE=false
until $DONE ;do
read || DONE=true
# process $REPLY here
done < /path/to/file.in
DONE=false
直到完成;做
read | | DONE=true
#在这里处理$REPLY
完成
如何重写此解决方案,使其行为与我之前使用的
循环完全相同,即不硬编码输入文件的位置?在第一个示例中,我假设您正在从stdin读取。要对第二个代码块执行相同的操作,您只需删除重定向和echo$REPLY:
DONE=false
until $DONE ;do
read || DONE=true
echo $REPLY
done
我使用以下构造:
while IFS= read -r LINE || [[ -n "$LINE" ]]; do
echo "$LINE"
done
除了输入中的空字符外,它几乎可以处理任何内容:
- 以空行开头或结尾的文件
- 以空格开头或结尾的行
- 没有终止换行符的文件
这里的基本问题是,read
遇到EOF时将返回errorlevel 1,即使它仍然正确地输入变量
因此,您可以在循环中立即使用errorlevel ofread
,否则最后的数据将不会被解析。但您可以这样做:
eof=
while [ -z "$eof" ]; do
read SCRIPT_SOURCE_LINE || eof=true ## detect eof, but have a last round
echo "$SCRIPT_SOURCE_LINE"
done
如果您想要一种非常可靠的方式来解析行,您应该使用:
IFS='' read -r LINE
记住:
- NUL字符将被忽略
- 如果您坚持使用
echo
模仿cat
的行为,则需要在检测到EOF时强制执行echo-n
(您可以使用条件[“$EOF”==true]
)
使用grep
和while循环:
while IFS= read -r line; do
echo "$line"
done < <(grep "" file)
当IFS=read-r行时;执行
回音“$line”
完成<@Netcoder的答案是好的,这种优化消除了虚假的空行,还允许最后一行没有换行,如果原来是这样的话
DONE=false
NL=
until $DONE ;do
if ! read ; then DONE=true ; NL='-n ';fi
echo $NL$REPLY
done
我使用了它的一个变体来创建两个函数,允许包含“[”的文本管道,以使grep满意。(您可以添加其他翻译)
(传递-由于$1启用管道,否则只转换参数)请尝试使用GNU Coreutils,如tee、cat等,而不是read
来自stdin
readvalue=$(tee)
echo $readvalue
从文件
readvalue=$(cat filename)
echo $readvalue
这是我一直使用的模式:
while read -r; do
echo "${REPLY}"
done
[[ ${REPLY} ]] && echo "${REPLY}"
这是因为即使循环结束时读取的“test”以非零代码退出,read
仍然填充内置变量$REPLY
(或您选择用读取
指定的任何变量).啊,重定向让我很困惑。谢谢你的回答,它就像一个符咒!如果有最后一行换行符,要避免处理额外的(空)行,请在包含读取
:[!$REPLY]]的行后添加此内容&&continue
@Dennis:这似乎跳过了所有的空行,这正是我在本例中想要的。谢谢!您不需要在IFS中包含换行符;您只需将其设置为空字符串即可。此外,要使此POSIX兼容(目前它只在bash中工作,而不是/bin/sh
),请执行IFS=''read-r LINE | |[-n“$LINE”]
注意,如果EOF中还没有换行符,则会在EOF中添加一个额外的换行符。第三条注意:POSIX标准就是这样定义一行的(第3206行):
while read -r; do
echo "${REPLY}"
done
[[ ${REPLY} ]] && echo "${REPLY}"