2

我有一个在最后一行末尾没有 EOL 的文件。当我从中读取的 bash 脚本没有处理最后一行时,我注意到了这一点。

我是这样读的:

while read LINE
do
    ...
done <thefile

该文件已提供给我,因此在它登陆我的系统之前我无能为力(Linux - OpenSuSE 10.2)。我确实dos2unix在文件上运行,但这并不能解决丢失的 EOL。

我见过几个涉及viand的解决方案ed,但它们有点笨拙,我希望有一个更整洁的解决方案,也许使用sed,我可以在我的 bash 脚本中使用?

奇怪vi的是,当我归档并执行 a时,我可以在最后一行的末尾:set list看到一个“ ”。$我原以为它会丢失,因为我认为“ $”代表\n。或者换行符和换行符之间可能有区别?

4

5 回答 5

5

如果文件还没有换行符(并且不是空白),这是一个在文件末尾添加换行符的选项:

if [ -s "$thefile" ] && [ "$(tail -c1 "$thefile"; echo x)" != $'\nx' ]; then
    echo >>"$thefile"
fi

或者,这里有一个简单的方法来修改循环以处理最后一个换行符之后的任何内容:

while read LINE || [ -n "$LINE" ]
do
...
于 2012-05-09T15:04:46.933 回答
4

这将在文件末尾添加一个换行符:

echo >> thefile
于 2012-05-09T13:56:49.377 回答
4

sed -i -e '$a\' "path"只有在没有换行符的情况下才会在 EOF 处添加换行符(跳转后的说明)。

如果要处理在 EOF 处可能没有换行符的文件,则必须检查read循环后是否存在输出变量:

while read LINE
do
    ...
done <thefile

if [ "${LINE+defined}" = defined ]
then
    ...
fi

不是很优雅,但至少您不必在处理之前修改输入。

于 2012-05-09T14:03:51.577 回答
1

几个实用程序在输出末尾添加换行符。例如,您可以使用 cut 并执行以下操作:

cut -b 1- < thefile | 
while read LINE; do ...; done

(可能不是所有 cut 的实现都像我描述的那样,但很多都这样做。)

罗伯特的解决方案可能是最简单的,如果你不能真正改变文件,你可以这样做:

{ cat thefile; echo; } | while read ...

请注意,将 while 放入管道中会将其放入子进程中,这可能会对脚本产生影响(例如,在循环中进行的分配不会持续存在),因此您可能需要使用临时文件或命名管道来修改数据。

于 2012-05-09T14:08:39.880 回答
0

[ -n "$l" ][[ $l ]]可以在 bash中替换。[[ $l ]]相当于[[ -n $l ]]$l不必引用,因为在内部不执行分词和路径名扩展[[

$ printf 'x\ny' | while IFS= read -r l; do echo "$l"; done
x
$ printf 'x\ny' | while IFS= read -r l || [[ $l ]]; do echo "$l"; done
x
y

$(tail -c1)仅当文件以换行符结尾或为空时才为空。$()从末尾删除换行符,tail -c1对于空文件为空。-s测试文件是否存在且不为空。

f=/tmp/some\ file
[[ -s $f && $(tail -c1 "$f") ]] && printf \\n >> "$f"

sed -n p(不打印,打印)是sed '$a\'. BSD seds 需要-i ''而不仅仅是-i.

sed -i '' -n p *.txt
于 2013-04-24T09:55:09.287 回答