如何在 unix 中删除文件的最后一个字符?

新手上路,请多包涵

假设我有一些任意的多行文本文件:

 sometext
moretext
lastline

如何仅删除文件的最后一个字符(e,而不是换行符或 null)而不使文本文件无效?

原文由 MaxPRafferty 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.7k
2 个回答

一种更简单的方法( 输出到 stdout ,不更新输入文件):

 sed '$ s/.$//' somefile

  • $ 是一个仅匹配最后一个输入行的 Sed 地址,因此导致以下函数调用( s/.$// )仅在最后一行执行。

  • s/.$// 用空字符串替换(在本例中为 last )行的最后一个字符;即,有效地删除最后一个字符。 (在换行符之前)就行了。

. 匹配行中的任何字符,并在其后跟 $ 将匹配锚定到行尾;注意 $ 在这个 正则表达式 中的使用在概念上是相关的,但在技术上与之前使用 $ 作为 Sed 地址 不同。

  • 使用标准输入的示例(假设 Bash、Ksh 或 Zsh):
     $ sed '$ s/.$//' <<< $'line one\nline two'
    line one
    line tw

要 _更新输入文件_(如果输入文件是符号链接,则不要使用):

 sed -i '$ s/.$//' somefile

笔记:

  • 在 macOS 上,您必须使用 -i '' 而不仅仅是 -i ;有关与 -i 相关的陷阱的概述,请参阅 此答案 的下半部分。
  • 如果您需要处理非常大的输入文件和/或性能/磁盘使用是一个问题 ,并且 您正在使用 GNU 实用程序 (Linux),请参阅 ImHere 的有用答案

原文由 mklement0 发布,翻译遵循 CC BY-SA 4.0 许可协议

truncate

 truncate -s-1 file

从同一文件的末尾删除一个 (-1) 字符。就像 >> 一样,将附加到同一个文件。

这种方法的问题在于,如果它存在,它不会保留尾随换行符。

解决方案是:

 if     [ -n "$(tail -c1 file)" ]    # if the file has not a trailing new line.
then
       truncate -s-1 file           # remove one char as the question request.
else
       truncate -s-2 file           # remove the last two characters
       echo "" >> file              # add the trailing new line back
fi

这是有效的,因为 tail 采用最后一个字节(而不是 char)。

即使是大文件也几乎不需要时间。

为什么不 sed

sed '$ s/.$//' file 这样的 sed 解决方案的问题在于它首先读取整个文件(大文件需要很长时间),然后您需要一个临时文件(与原始文件大小相同):

 sed '$ s/.$//' file  > tempfile
rm file; mv tempfile file

然后移动临时文件以替换文件。

原文由 user8017719 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题