echo -n 'I hate cats' > cats.txt
sed -i '' 's/hate/love/' cats.txt
这会正确更改文件中的单词,但也会在文件末尾添加换行符。为什么?这只发生在 OSX 中,而不是 Ubuntu 等。我该如何阻止它?
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
)
避免这个问题的一个好方法是使用 perl 而不是 sed。Perl 将尊重原始文件中的 EOF 换行符或缺少它。
echo -n 'I hate cats' > cats.txt
perl -pi -e 's/hate/love/' cats.txt
请注意,GNU sed 不会在 Mac OS 上添加换行符。
您可以做的另一件事是:
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 以换行符结尾,它就会被保留。如果没有,则不会添加一个。
这对我有用。我不必使用中间文件。
OUTPUT=$( echo 'I hate cats' | sed 's/hate/love/' )
echo -n "$OUTPUT"