在没有换行的情况下用 echo 附加文本

cho*_*ijj 29 shell io-redirection echo text-processing

我想将文本附加到文件中,例如echo "abc" >>file.txt.

但这abc在新行之后添加

如何abc在没有换行的情况下使用 echo 在文件末尾添加?

flu*_*ffy 31

假设文件还没有以换行符结尾,并且您只想追加一些文本而不添加文本,则可以使用-n参数,例如

echo -n "some text here" >> file.txt
Run Code Online (Sandbox Code Playgroud)

但是,某些 UNIX 系统不提供此选项;如果是这种情况,您可以使用printf,例如

printf %s "some text here" >> file.txt
Run Code Online (Sandbox Code Playgroud)

(最初的%s论点是防止附加文本中包含%格式字符)

来自man echo(在 macOS High Sierra 上):

-n

不要打印尾随的换行符。这也可以通过附加'\c'到字符串的末尾来实现,正如 iBCS2 兼容系统所做的那样。请注意,此选项以及 的效果'\c'是由 Cor 修订的 IEEE Std 1003.1-2001(“POSIX.1”)中实现定义的。1-2002 年。强烈建议以最大可移植性为目标的应用程序用于printf(1)抑制换行符。


Gil*_*il' 21

echo "abc" >>file.txt在 之后 abc而不是之前放置一个换行符。如果您以abc自己的行结束,则意味着之前的换行符abc已经存在于file.txt.

请注意,文本文件以换行符结尾是完全正常的。在 unix 上,一行由非空字符序列组成?或换行符后跟换行符。1因此,任何非空文本文件都以换行符结尾。

如果你想在文件的最后一行添加文本,那么你不能用 来做>>,因为这总是附加到文件中,所以它总是写在最后一个换行符之后。相反,您需要一个能够修改现有文件的工具。例如,您可以使用sed

sed '$ s/$/abc/' file.txt >file.txt.new && mv file.txt.new file.txt
Run Code Online (Sandbox Code Playgroud)

在sed命令中,第一个$意思是“只在最后一行执行下面的命令”,该命令s/REGEX/REPLACEMENT/将REGEX替换为REPLACEMENT,正则表达式$匹配到行尾。

Linux 的 sed 命令有一个内置功能可以自动执行此创建新文件和替换序列,因此您可以将其缩短为

sed -i '$ s/$/abc/' file.txt
Run Code Online (Sandbox Code Playgroud)

? 这是一个空字节,ASCII 称其为 NUL,Unicode 称其为 U+0000。文本处理程序可能会也可能不会处理这个字符。
1 请参阅IEEE 1003.1-2008:2016基本定义章节的“定义”部分中Text FileLineNewline Character的定义。

  • 您的第二段是否暗示不以换行符结尾的文件不是文本文件?例如,如果我采用以新行结尾的现有 ASCII 文本文件并附加一个单字节“0x41”(ASCII“A”),从技术上讲,它不再是文本文件?如果是这样,我建议强调这一点,因为它是一个不直观的定义;如果没有,稍加修改措辞可能有助于避免混淆。 (2认同)
  • @DavidZ:这是 Unixland 中文本文件的标准定义。IIRC 它甚至在 POSIX 的某个地方。 (2认同)
  • @Kevin 有趣,我以前从未听说过。好吧,即使它是标准的,我确实认为这有点不直观。 (2认同)

Rom*_*est 16

我认为使用echo命令是不可能的,请改用以下sed方法:

sed -i '$ s/$/abc/' file.txt
Run Code Online (Sandbox Code Playgroud)
  • -i-就地修改文件
  • $ - 表示最后一条记录/行
  • s/$/abc/-$用子字符串替换行尾abc(最后一条记录)

  • 请注意,“就地”并不真正意味着就地。这意味着“将编辑的内容写入现有文件旁边的临时命名文件,然后替换它”。您可以通过查看带有 `date >file; 的 inode 来证明这一点。ls -i 文件;sed -i 's/201/ZZZ/' 文件;ls -i 文件` (2认同)
  • 我以为你会,但我担心你强调 _inplace_ OP 之夜认为它可以用来避免双磁盘空间使用,例如使用大文件。 (2认同)

roa*_*ima 12

如果您有该truncate命令并且您的文本文件的最后一个字符是 NL,您可以将其删除,然后像这样附加您的文本:

truncate --size -1 file.txt
echo "abc" >>file.txt
Run Code Online (Sandbox Code Playgroud)

(请注意,它不truncate关心文件内容,在此示例中只是将文件大小减少了一个字节。如果您的最后一个字符不是单个字节,即它是一个多字节“宽”字符,那么您将引入损坏。)


Sté*_*las 5

你想要的是将它添加到最后一行的末尾,所以就在最后一行的分隔符之前,所以就在文件的最后一个字符之前。

使用ksh93,您可以执行以下操作:

echo abc 1<> file >#((EOF - 1))
Run Code Online (Sandbox Code Playgroud)

在stdout 上1<>以读+写模式(更重要的是没有截断)打开文件的标准运算符在哪里,并且>#((...))是特定于ksh93 的搜索运算符(这里是在最后一个字节之前搜索)。请注意,echowrites覆盖了abc<newline>那里的a换行符并echo添加了自己的换行符。

zsh相当于:

zmodload zsh/system
{sysseek -w end -u 1 -1 && echo abc} 1<> file
Run Code Online (Sandbox Code Playgroud)

尽管对于更精确的等效项,您还需要在查找失败时打印错误消息:

zmodload zsh/system
if sysseek -w end -u 1 -1; then
  echo abc
else
  syserror -p "$0: $LINENO: seek: "
fi 1<> file
Run Code Online (Sandbox Code Playgroud)