附加带有回声的文本而无需换行


15

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

但这abc在新行之后添加

如何abc在没有换行的情况下在文件末尾添加回显?


2
该文件已经有换行符,您只是在其后添加。因此,您必须将最后一行的换行符替换为“ abc”。
ctrl-alt-delor

欢迎使用StackExchange!您的问题很好;如果您指定了文件内容的示例(添加之前,添加之后得到的内容,想要的内容),那就更好了。我之所以这样说,是因为答案之一是如何在abc没有最后一个换行符的情况下进行添加,而换行符(在认真地阅读了您的问题之后)似乎并不是您想要的。
Law17年

Answers:


19

echo "abc" >>file.txt abc而不是之前放置换行符。如果您以abc自己的一行结尾,abc则表示之前的换行符已存在于中file.txt

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

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

sed '$ s/$/abc/' file.txt >file.txt.new && mv file.txt.new file.txt

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

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

sed -i '$ s/$/abc/' file.txt

这是一个空字节,ASCII调用NUL,而Unicode调用U + 0000。文本处理程序可能会也可能无法应付此字符。
1 请参见IEEE 1003.1-2008:2016 的“ 基本定义”一章的“定义”部分中的“ 文本文件”,“ ”和“ 换行符 ”的定义。


2
您的第二段是否意味着不以换行符结尾的文件不是文本文件?例如,如果我采用一个以换行结尾的现有ASCII文本文件并附加一个字节0x41(ASCII 'A'),那么从技术上讲它不再是文本文件了吗?如果是这样,我建议强调这一点,因为这是一种不直观的定义。如果不是这样,略微改变措词可能有助于避免混淆。
David Z

2
@DavidZ:这是Unixland中文本文件的标准定义。IIRC它甚至在POSIX中的某个地方。
凯文(Kevin)

1
@Kevin有趣的是,我之前从未听说过。好吧,即使它是标准的,我也认为这有点不直观。
大卫Z

15

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

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

2
请注意,“到位”并不是真正的到位。这意味着“将已编辑的内容与现有文件一起写入一个临时命名文件,然后替换它”。您可以通过date >file; ls -i file; sed -i 's/201/ZZZ/' file; ls -i file
roaima

@roaima,我知道sed更改了inode编号。
RomanPerekhrest

2
我以为你会一直,但我担心的是你的重点就地的OP晚上认为这可以用来避免双重磁盘空间使用情况,例如,用一个大文件。
roaima

@roaima,晚上想 ->可能想...
RomanPerekhrest

如果我想用变量替换abc怎么办?使用'$ s/$/$1/'版画$1
Florian Castelain

13

假设文件尚未以换行符结尾,而您只是想添加一些文本而不添加文本,则可以使用-n参数,例如

echo -n "some text here" >> file.txt

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

printf %s "some text here" >> file.txt

(初始%s参数是要防止其中包含%格式字符的其他文本)

man echo(在macOS High Sierra上):

-n

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


很显然,以换行符结尾。 echo -n不会在末尾放置换行符abc,但abc仍要在换行符之前,这是用户希望避免的。
库沙兰丹

@Kusalananda我的回答更多地是基于这样的假设,即OP会尝试更改其过程,从而使伪造\n不会首先出现。更多的选择会更好,尤其是当它们不需要每次更改时都必须重写整个文件时(如果反复执行,它会变得很慢,并且会在多项式时间内运行)。
蓬松的

9

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

truncate --size -1 file.txt
echo "abc" >>file.txt

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


5

您想要的是将其添加到最后一行的末尾,即紧接在最后一行的分隔符之前,也就是恰好在文件的最后一个字符之前。

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

echo abc 1<> file >#((EOF - 1))

在stdout上1<>以读/写模式(更重要的是没有截断)打开文件的标准操作符在哪里,并且>#((...))是ksh93特定的查找操作符(此处在最后一个字节之前查找)。请注意,echoabc<newline>在其中a覆盖那里的换行符并echo添加其自己的换行符的位置进行写入。

zsh相当于:

zmodload zsh/system
{sysseek -w end -u 1 -1 && echo abc} 1<> file

尽管要获得更精确的等效结果,但在无法搜索时,您还需要打印一条错误消息:

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

-1

可能是UUOC,但您也可以这样做:

echo "$(cat file.txt)abc" >file.txt

正如Gilles指出的,此命令是有限的:

这通常有效,但如果有时文件末尾有空白行,而紧接在其后有空白行,则无效。例如,具有固定行数的文件,其中最后一行最初是空的,并且随着时间的推移而扩展,而倒数第二行有时可能是空的。

此外,请谨慎使用cat您不熟悉的文件:

结论

使用sed


2
这通常有效,但如果有时文件末尾有空白行,而紧接在其后有空白行,则无效。例如,具有固定行数的文件,其中最后一行最初是空的,并且随着时间的推移而扩展,而倒数第二行有时可能是空的。
吉尔(Gilles)'所以

我应该删除它吗?我绝对认为罗马/您的答案是正确的选择,但我知道我个人喜欢查看替代方法,OP确实要求echo:p
jesse_b

1
同样,这会将整个文件放在命令行上
n.caillou

@ n.caillou是吗?这不会将任何内容打印到STDOUT。
jesse_b

2
嗯,所有这些漏洞都与无关cat,而与发送到终端的任意转义序列有关。
ilkkachu
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.