18
echo -n 'I hate cats' > cats.txt
sed -i '' 's/hate/love/' cats.txt

这会正确更改文件中的单词,但也会在文件末尾添加换行符。为什么?这只发生在 OSX 中,而不是 Ubuntu 等。我该如何阻止它?

4

5 回答 5

15
echo -n 'I hate cats' > cats.txt

此命令将使用单引号之间的 11 个字符填充“cats.txt”的内容。如果你在这个阶段检查cats.txt 的大小,它应该是11 个字节。

sed -i '' 's/hate/love/' cats.txt

此命令将逐行读取cats.txt 文件,并将其替换为每行已将“hate”的第一个实例替换为“love”的文件(如果存在这样的实例)。重要的部分是理解什么是线。从 sed 手册页:

 Normally, sed cyclically copies a line of input, not including its
 terminating newline character, into a pattern space, (unless there is
 something left after a ``D'' function), applies all of the commands
 with addresses that select that pattern space, copies the pattern
 space to the standard output, appending a newline, and deletes the
 pattern space.

注意appending a newline部分。在您的系统上,sed 仍然将您的文件解释为包含单行,即使没有终止换行符。所以输出将是 11 个字符,加上附加的换行符。在其他平台上,情况不一定如此。有时 sed 会完全跳过文件中的最后一行(实际上是删除它),因为它不是真正的一行!但是在您的情况下, sed 基本上是在为您修复文件(作为其中没有行的文件,它是 sed 的错误输入)。

在此处查看更多详细信息:为什么文本文件应以换行符结尾?

请参阅此问题以了解解决问题的另一种方法:SED 在末尾添加新行

如果您需要一个不添加换行符的解决方案,您可以使用gsed( brew install gnu-sed)

于 2012-11-12T00:18:25.947 回答
3

避免这个问题的一个好方法是使用 perl 而不是 sed。Perl 将尊重原始文件中的 EOF 换行符或缺少它。

echo -n 'I hate cats' > cats.txt
perl -pi -e 's/hate/love/' cats.txt
于 2018-03-01T06:12:06.700 回答
1

请注意,GNU sed 不会在 Mac OS 上添加换行符。

于 2016-09-13T11:01:11.840 回答
0

您可以做的另一件事是:

echo -n 'I hate cats' > cats.txt
SAFE=$(cat cats.txt; echo x)
SAFE=$(printf "$SAFE" | sed -e 's/hate/love/')
SAFE=${SAFE%x}

这样,如果cats.txt 以换行符结尾,它就会被保留。如果没有,则不会添加一个。

于 2014-09-09T07:04:53.440 回答
0

这对我有用。我不必使用中间文件。

OUTPUT=$( echo 'I hate cats' | sed 's/hate/love/' )
echo -n "$OUTPUT"
于 2014-12-01T21:34:40.110 回答