vim / vi / sed:从文件末尾开始一定数量的行

就像我们可以从vim文件的开头删除(或者replace,或者抽取等等)第4行到第6行:

:4,6d 

我想从文件末尾删除(或者replace,或者抽取等)第四行到第六行。 这意味着,如果该文件有15行,我会做:

 :10,12d 

但是,当他们不知道文件中有多less行时,就不能这样做 – 我将在一批文件上使用它。 我如何在vim和sed中执行此操作?

事实上,我看过这篇文章 ,但没有发现它有用。

那么,使用vim你可以尝试以下 – 无论如何,这很直观:

 :$-4,$-5d 

现在,使用sed我找不到一个确切的方法来做到这一点,但如果你可以使用sed以外的东西,这里headtail的解决方案:

 head -n -4 file.txt && tail -2 file.txt 

在Vim中,你可以从$减去行号,这代表最后一行,例如,这将在最后3行:

 :$-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 

从文件末尾的第4行到第6行:使用tac来反转文件

 tac filename | sed 4,6d | tac 

你可以用awk使用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 

这可能适用于你(GNU sed):

 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行的$ (文件结束),则循环回到开始,即label :a
  • P;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