说我有一些任意的多行文本文件:
sometext
moretext
lastline
如何在不使文本文件无效的情况下仅删除文件的最后一个字符(e,而不是换行符或null)?
答案 0 :(得分:70)
一种更简单的方法(输出到stdout ,不会更新输入文件):
sed '$ s/.$//' somefile
$
是一个Sed地址,仅匹配最后一个输入行,因此导致以下函数调用(s/.$//
)仅在最后一行执行。s/.$//
用空字符串替换(在本例中为 last )行的最后一个字符;即,有效地删除最后一个字符。 (换行前)。在线上
.
匹配该行上的任何字符,然后使用$
将匹配锚定到该行的末尾;请注意在此正则表达式中$
的使用在概念上是如何相关的,但在技术上与先前使用$
作为Sed 地址不同。 stdin输入示例(假设Bash,Ksh或Zsh):
$ sed '$ s/.$//' <<< $'line one\nline two'
line one
line tw
要更新输入文件(如果输入文件是符号链接,请不要使用):
sed -i '$ s/.$//' somefile
注意:
*在OSX上,您必须使用-i ''
而不是-i
;有关与-i
相关的陷阱的概述,请参阅my answer here的下半部分
*如果您需要处理非常大的输入文件和/或性能/磁盘使用是一个问题和您正在使用 GNU 实用程序(Linux),请参阅{{ 3}}
答案 1 :(得分:36)
<强> 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解决方案的问题在于它首先读取整个文件(花费很长时间使用大文件),然后你需要一个临时文件(与原始文件大小相同):< / p>
sed '$ s/.$//' file > tempfile
rm file; mv tempfile file
然后移动tempfile以替换该文件。
答案 2 :(得分:4)
这是使用ex
的另一个,我发现它不像sed解决方案那样神秘:
printf '%s\n' '$' 's/.$//' wq | ex somefile
$
转到最后一行,s
删除最后一个字符,wq
是众所周知的(对vi用户)写+退出。
答案 3 :(得分:2)
如果目标是删除最后一行中的最后一个字符,则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
它将所有数据存储到一个数组中,然后将其打印出来并更改最后一行。
答案 4 :(得分:1)
经过一大堆不同的策略(并避免使用sed -i或perl)之后,我发现这样做的最好方法是:
sed '$! { P; D; }; s/.$//' somefile
答案 5 :(得分:1)
编辑回答
我创建了一个脚本并将您的文本放在我的桌面上。此测试文件保存为&#34; old_file.txt&#34;
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
我为我之前的回答道歉(没有仔细阅读)
答案 6 :(得分:1)
只是一句话:sed会暂时删除该文件。 因此,如果您正在拖尾文件,那么在重新发出tail命令之前,您将收到“No such file or directory”警告。
答案 7 :(得分:0)
sed 's/.$//' filename | tee newFilename
这应该可以帮到你。