就像我们可以在vim中从文件开头删除(或替换、复制等)第4到6行一样:
:4,6d
我想删除(或替换、yank等)文件末尾第4行到第6行。也就是说,如果文件有15行,我会执行以下操作:
:10,12d
但是当他们不知道文件中有多少行时,就无法这样做——而我将在许多文件的批处理中使用它。我应该如何在vim和sed中执行此操作?
我确实看过这篇文章,但并没有发现它有用。
好的,使用vim
,你可以尝试以下内容-这相当直观,无论如何:
:$-4,$-5d
现在,使用 sed
我找不到确切的解决方法,但如果您可以使用除了 sed
之外的其他东西,这里有一个使用 head
和 tail
的解决方案:
head -n -4 file.txt && tail -2 file.txt
Vim中,你可以从$
(代表最后一行)中减去行号,例如,在最后三行上执行:
:$-2,$substitute/...
在sed中,这并不容易,因为它作用于字符的流,并且不能简单地返回。您需要在“保留空间”中存储一些最近看到的行号,并在流的结尾处理保留空间。 以下是来自sed1line.txt的一些示例:
# print the last 10 lines of a file (emulates "tail")
sed -e :a -e '$q;N;11,$D;ba'
# print the last 2 lines of a file (emulates "tail -2")
sed '$!N;$!D'
# delete the last 2 lines of a file
sed 'N;$!P;$!D;$d'
# delete the last 10 lines of a file
sed -e :a -e '$d;N;2,10ba' -e 'P;D' # method 1
sed -n -e :a -e '1,10!{P;N;D;};N;ba' # method 2
awk 'NR==FNR{numLines++;next} {fromEnd = numLines - FNR} fromEnd > 6 || fromEnd < 4' file file
awk 'NR==FNR{numLines++;next} {fromEnd = numLines - FNR} fromEnd < 6 && fromEnd > 4' file file
sed -r ':a;${s/([^\n]*\n){3}//;q};N;7,$!ba;P;D' file
这是通过在模式空间(PS)中创建一个6行的移动窗口,然后在遇到最后一行时删除前三行来实现的。
:a
是一个循环标签${s/([^\n]*\n){3}//;q}
删除文件末尾PS中的前三行并退出。N
添加一个换行符和下一行到PS中。7,$!ba
' 如果不是第7行到$(文件结尾)即第1行到第6行,则回到开头即标签:aP;D
对于行范围7到$(文件结尾),打印PS中第一个换行符之前的内容,然后删除包括第一个换行符在内的所有内容,并开始新的循环。倒数第二个子句默认创建窗口,因为行 1
到 6
被附加到 PS 中。从第 7
行到结尾,添加一行并打印删除第一行。
或者:
sed -e ':a' -e '$s/\([^\n]*\n\)\{3\}//' -e '$q' -e 'N' -e '7,$!ba' -e 'P' -e 'D' file