我想找到文件中的最后一行文本,并删除其末尾的逗号。我已经问过这个问题了,但是,在我得到答案后,我意识到我的问题不够具体。
该sed
命令将转到文件的最后一行并对其执行操作。就我而言,我想删除结尾的逗号:
sed -i '$ s/",/"/g' file.txt
所以这:
blah blah blah,
blah blah blah,
blah blah blah,
...变成这样:
blah blah blah,
blah blah blah,
blah blah blah
然而,如果最后一行文本后面有空行,这将不起作用在文件中。
我一直在寻找获取最后一行文本的方法,但还没有想出任何我可以理解和应用的方法。我还寻找了删除所有尾随空白行的方法,并找到了以下命令:
sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' *.txt
但它对我不起作用(它似乎只是在命令行上输出我的文件的内容)。无论如何,这都是不优雅的。我不想删除尾随的空白行,最好只识别最后一行包含文本的内容并对其采取行动。
如何删除最后一行的逗号文本的在一个目录的多个文件中?
答案1
对于大文件,使用 Guru 的答案,速度更快。然而,在小文件(<25 行)上,我发现这稍微快一些(假设您有 GNU tac):
tac file | awk '!/^[[:blank:]]*$/{i++;if(i==1){sub(",$","")}}1' | tac
答案2
回答
perl -0777 -p -i -e 's/,(\n*)\Z/\1/m' *.txt
将删除所有以 结尾的文件中的最后一个 ',' .txt
,如果 ',' 后面仅跟有 0 个或多个换行符,然后是文件末尾。
从你的例子来看:
reedm@www:~/tmp $ cat > test.txt
blah blah blah,
blah blah blah,
blah blah blah,
reedm@www:~/tmp $ perl -0777 -p -i -e 's/,(\n*)\Z/\1/m' *.txt
reedm@www:~/tmp $ cat test.txt
blah blah blah,
blah blah blah,
blah blah blah
reedm@www:~/tmp $
瓦?
即使在最好的情况下,Perl 也是一头深奥的野兽,而 Perl 的俏皮话可能特别神秘。
该-e
标志允许我们在命令行上传递 perl 程序。在本例中,“s/regex/replace/flags”就是程序。
该-p
标志使 perl 在循环中对-0
所提供的每个文件名的每个“行”(请参阅 参考资料)应用您提供的程序。
该-i
标志使 perl 用程序的输出替换文件,而不是将输出打印到标准输出。
该-0
标志更改 perl 用于将文件分成“行”的分隔符。0777
是一个特殊值,按照惯例使用它使 perl 将整个文件读取到单个“行”中。
由于使用了一些特定于 Perl 的技巧,正则表达式有些复杂:
- 首先,
m
末尾的标志导致正则表达式在多行上运行。 ,
很简单,并且匹配单个逗号。(\n*)
匹配一行中的 0 个或多个换行符,并将它们存储为子模式((
和)
字符表示子模式)。由于这是第一个子模式,我们可以\1
在替换部分中使用它来表示“无论该子模式匹配什么”。\Z
是 Perl 特定的扩展名,并且匹配正在使用的字符串的结尾——在本例中,这是整个文件。- 在替换部分中,我们
\1
仅用一系列换行符替换匹配项,并删除逗号。
有关 perl 正则表达式和 perl 命令行标志的 man 信息,请分别查看perlre
和的手册页perlrun
。
答案3
如果 Perl 解决方案适合您:
perl -00pe 's/(.*),/$1/s' file
要将更改保存在文件本身中:
perl -i -00pe 's/(.*),/$1/s' file
要将其应用于多个文件:
perl -i -00pe 's/(.*),/$1/s' *.txt
答案4
sed
可以进入多行搜索和替换模式,以便它可以将整个文件内容作为“模式空间”中的单行进行处理。
(注意:FreeBSDsed
需要选项序列-n -i -e
才能正确进行就地文件编辑。)
# delete the last , in the last non-empty line of a file
# cf. http://austinmatzko.com/2008/04/26/sed-multi-line-search-and-replace/
cat -n testfile
sed -n -i -e '
# if the first line copy the pattern to the hold buffer
1h
# if not the first line then append the pattern to the hold buffer
1!H
# if the last line then ...
$ {
# copy from the hold to the pattern buffer
g
# remove last , in last non-empty line of file
#s/,\([^,[:cntrl:]]*\n*\)$/\1/
s/,\([^,]*\)$/\1/
p
}' testfile