Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vim/vi/sed: Act on a certain number of lines from the end of the file

Tags:

linux

bash

vim

sed

awk

Just as we can delete (or substitute, or yank, etc.) the 4th to 6th lines from the beginning of a file in vim:

:4,6d 

I'd like to delete (or substitute, or yank, etc.) the 4th last to the 6th lines from the end of a file. It means, if the file has 15 lines, I'd do:

:10,12d

But one can't do this when they don't know how many lines are in the files -- and I'm going to use it on a batch of many files. How do I do this in vim and sed?

I did in fact look at this post, but have not found it useful.

like image 913
Pearson Avatar asked Jan 02 '13 01:01

Pearson


People also ask

How do I select the number of lines in vim?

If you want to select the entire line in a file, press V. Now when you press k or j to go up and down, vim will select the entire line above and below your cursor. Finally, you can select text in columns by pressing ctrl+v and moving up or down the block.

Does vim add newline at end of file?

Vim doesn't show latest newline in the buffer but actually vim always place EOL at the end of the file when you write it, because it standard for text files in Unix systems. You can find more information about this here. In short you don't have to worry about the absence a new lines at the end of the file in vim.


2 Answers

Well, using vim you can try the following -- which goes quite intuitive, anyway:

:$-4,$-5d

Now, using sed I couldn't find an exact way to do it, but if you can use something other than sed, here goes a solution with head and tail:

head -n -4 file.txt && tail -2 file.txt
like image 179
Rubens Avatar answered Nov 07 '22 04:11

Rubens


In Vim, you can subtract the line numbers from $, which stands for the last line, e.g. this will work on the last 3 lines:

:$-2,$substitute/...

In sed, this is not so easy, because it works on the stream of characters, and cannot simply go back. You would have to store a number of last seen lines in the hold space, and at the end of the stream work on the hold space. Here are some recipes from 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
like image 21
Ingo Karkat Avatar answered Nov 07 '22 05:11

Ingo Karkat