Linux上的文件中缺少EOL字符

时间:2012-05-09 13:55:32

标签: linux bash shell sed

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

我是这样读的:

while read LINE
do
    ...
done <thefile

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

我看过几个涉及vied的解决方案,但它们有点笨重,我希望有一个更简洁的解决方案,可能使用sed,我可以在我的bash脚本中使用?

奇怪的是,当我vi该文件并执行:set list时,我可以在最后一行的末尾看到“$”。因为我认为“$”代表\n,所以我期待失踪。或者换行和行尾之间可能存在差异?

5 个答案:

答案 0 :(得分:5)

如果文件的末尾没有(并且不是空白),可以选择在文件末尾添加换行符:

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

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

while read LINE || [ -n "$LINE" ]
do
...

答案 1 :(得分:3)

这会在文件末尾添加换行符:

echo >> thefile

答案 2 :(得分:2)

sed -i -e '$a\' "path"只会在EOF上添加换行符(如果它还没有换行符)(跳转后的解释)。

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

while read LINE
do
    ...
done <thefile

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

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

答案 3 :(得分:1)

多个实用程序在输出结尾添加换行符。例如,您可以使用cut并执行:

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

(可能并非所有剪切的实现都像我描述的那样,但很多都是。)

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

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

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

答案 4 :(得分:0)

在pash中,

[ -n "$l" ]可以替换为[[ $l ]][[ $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