如何在 UNIX 中删除文件的最后一个字符?
- 2024-10-25 08:42:00
- admin 原创
- 60
问题描述:
假设我有一些任意的多行文本文件:
sometext
moretext
lastline
我怎样才能删除文件的最后一个字符(e,而不是换行符或空字符)而不使文本文件无效?
解决方案 1:
一种更简单的方法(输出到 stdout,不更新输入文件):
sed '$ s/.$//' somefile
$
是仅与最后一行输入匹配的 Sed 地址,从而导致以下函数调用(s/.$//
)仅在最后一行执行。s/.$//
用空字符串替换行(在本例中为最后一行)的最后一个字符;即有效地删除行上的最后一个字符(换行符之前)。
+ 注意:如果文件以*两个或更多*换行符结尾,则该命令为*无操作*。
.
匹配行中的任意字符,并在其后跟上将$
匹配锚定到行尾;请注意,$
此正则表达式$
中的使用在概念上是相关的,但在技术上与之前作为 Sed地址的用法不同。
带有 stdin 输入的示例(假设是 Bash、Ksh 或 Zsh):
$ sed '$ s/.$//' <<< $'line one
line two'
line one
line tw
也更新输入文件(如果输入文件是符号链接则不要使用):
sed -i '$ s/.$//' somefile
笔记:
在 macOS 上,您必须使用
-i ''
而不是仅仅使用-i
;有关与之相关的陷阱的概述,请参阅此答案-i
的下半部分。如果您需要处理非常大的输入文件和/或性能/磁盘使用情况令人担忧,并且您正在使用GNU实用程序(Linux),请参阅ImHere 的有用答案。
解决方案 2:
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 占用的是最后一个字节(而不是字符)。
即使文件很大,也几乎不需要时间。
为什么不sed
类似 sed 解决方案的问题sed '$ s/.$//' file
在于它首先读取整个文件(对于大文件需要很长时间),然后需要一个临时文件(与原始文件大小相同):
sed '$ s/.$//' file > tempfile
rm file; mv tempfile file
然后移动临时文件来替换该文件。
解决方案 3:
这是另一种使用方法ex
,我发现它并不像 sed 解决方案那么神秘:
printf '%s
' '$' 's/.$//' wq | ex somefile
转到$
最后一行,s
删除最后一个字符,这wq
就是众所周知的(对于 vi 用户而言)写入 + 退出。
解决方案 4:
经过大量尝试不同的策略(并避免使用 sed -i 或 perl)之后,我发现最好的方法是:
sed '$! { P; D; }; s/.$//' somefile
解决方案 5:
如果目标是删除最后一行的最后一个字符,则awk
应该这样做:
awk '{a[NR]=$0} END {for (i=1;i<NR;i++) print a[i];sub(/.$/,"",a[NR]);print a[NR]}' file
sometext
moretext
lastlin
它将所有数据存储到一个数组中,然后将其打印出来并更改最后一行。
解决方案 6:
需要注意的是:sed 将暂时删除该文件。因此,如果您正在拖尾该文件,您将收到“没有这样的文件或目录”警告,直到您重新发出 tail 命令为止。
解决方案 7:
编辑答案
我创建了一个脚本并将您的文本放在我的桌面上。此测试文件保存为“old_file.txt”
sometext
moretext
lastline
后来我写了一个小脚本来获取旧文件并删除最后一行的最后一个字符
#!/bin/bash
no_of_new_line_characters=`wc '/root/Desktop/old_file.txt'|cut -d ' ' -f2`
let "no_of_lines=no_of_new_line_characters+1"
sed -n 1,"$no_of_new_line_characters"p '/root/Desktop/old_file.txt' > '/root/Desktop/my_new_file'
sed -n "$no_of_lines","$no_of_lines"p '/root/Desktop/old_file.txt'|sed 's/.$//g' >> '/root/Desktop/my_new_file'
打开我创建的 new_file,显示的输出如下:
sometext
moretext
lastlin
我为之前的回答道歉(没有仔细阅读)
解决方案 8:
sed 's/.$//' filename | tee newFilename
这应该可以完成你的工作。
解决方案 9:
几个 perl 解决方案,用于比较/参考:
(echo 1a; echo 2b) | perl -e '$_=join("",<>); s/.$//; print'
(echo 1a; echo 2b) | perl -e 'while(<>){ if(eof) {s/.$//}; print }'
我发现第一种将整个文件读入内存的方法通常非常有用(对于这个特定问题则不那么有用)。您现在可以执行跨越多行的正则表达式,例如将每 3 行某种格式合并为 1 个摘要行。
对于这个问题,版本truncate
会更快,sed
输入起来也更短。请注意,truncate
需要操作文件,而不是流。通常我发现sed
它缺乏 perl 的功能,我更喜欢扩展正则表达式/perl-regex 语法。但这个问题有一个很好的sed
解决方案。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件