Is there a command that will allow me to edit the last n lines in a file? I have several files, that all have a different number of lines inside. But I would like to modify the last n lines in each file. The goal is to replace commas with semicolons in the last n lines. But only in the very last n lines.

I do not want to delete any lines, I just want to replace every comma with a semicolon in the last n lines in each file.

Using the sed command I am able to replace the very last line with this command. As described here: How can I remove text on the last line of a file?

But this only enables me to modify the very last line, and not the last n number of lines.

share|improve this question
1  
Simply using sed '24,$s/,/:/g' filename where 24 is the starting line` – val0x00ff Jun 21 at 12:43

To replace commas with semicolons on the last n lines with ed:

n=3
ed -s input <<< '$-'$((n-1))$',$s/,/;/g\nwq'

Splitting that apart:

  • ed -s = run ed silently (don't report the bytes written at the end)
  • '$-' = from the end of the file ($) minus ...
  • $((n-1)) = n-1 lines ...
  • ( $' ... ' = quote the rest of the command to protect it from the shell )
  • ,$s/,/;/g = ... until the end of the file (,$), search and replace all commas with semicolons.
  • \nwq = end the previous command, then save and quit

To replace commas with semicolons on the last n lines with sed:

n=3
sed -i "$(( $(wc -l < input) - n + 1)),\$s/,/;/g" input

Breaking that apart:

  • -i = edit the file "in-place"
  • $(( ... )) = do some math:
  • $( wc -l < input) = get the number of lines in the file
  • -n + 1 = go backwards n-1 lines
  • ,\$ = from n-1 lines until the end of the file:
  • s/,/;/g = replace the commas with semicolons.
share|improve this answer
    
Can replace wc -l < input with wc -l input. Should be faster by a few nanoseconds :) – gardenhead Jun 21 at 17:09
1  
except that wc -l input outputs the filename as well; we only want the line count – Jeff Schaller Jun 21 at 17:38

Solution using tac and sed to replace every comma with a semicolon in the last 50 lines of file.txt:

tac file.txt | sed '1,50s/,/;/g' | tac
share|improve this answer

With GNU head and a Bourne-like shell:

n=20
{ head -n -"$n"; tr , ';'; } < file 1<> file

We're overwriting the file over itself. That's OK here for a byte-to-byte transliteration but wouldn't necessarily if the modification implies changing the size of the file (in which case, you'd want to replace 1<> file with > other-file && mv other-file file for instance).

share|improve this answer
1  
Here's docs for 1<>, which I was unfamiliar with. Also, sponge from moreutils is a good tool for pipelines where you want to overwrite your input. – Miles Jun 22 at 3:47

Lets assume we want to replace the last 7 lines of the following sequence with shell script and GNU implementation of sed:

$ seq 20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Step 1: lets get the last line number of sequence like the following. Take a look at this and that:

$ lastLine=`seq 20|sed -n '$='`

$ echo $lastLine 
20

Step 2: lets set the number of lines (at the end of sequence) we intend to edit:

$ numberOfLines=7

$ echo $numberOfLines 
7

Step 3: lets calculate the start line based on previous variables, like the following. Take a look at this:

$ startLine=`expr $lastLine - $numberOfLines + 1`

$ echo $startLine 
14

Step 4: Now, we can replace the last 7 lines of sequence with something else, like the following. Take a look at this:

$ seq 20|sed -e "$startLine,+$numberOfLines{s/[12]/WoW/}"
1
2
3
4
5
6
7
8
9
10
11
12
13
WoW4
WoW5
WoW6
WoW7
WoW8
WoW9
WoW0

Step 4 is using section 4.4 of sed man page which says:

'ADDR1,+N'
     Matches ADDR1 and the N lines following ADDR1.

Step 4, also is using double-quotes as mentioned here.


Well, the 4 steps are unnecessary if we use the answer of Gohu like this:

$ seq 20 |tac|sed -e '1,7{s/[12]/WoW/}'|tac
1
2
3
4
5
6
7
8
9
10
11
12
13
WoW4
WoW5
WoW6
WoW7
WoW8
WoW9
WoW0
share|improve this answer

Use tail and pipe to sed:

tail -n 20 file | sed 's/,/;/g'

This works on the file for the last 20 lines. If you want to have thee canges direct to the file use:

tail -n 20 file | sed -i 's/,/;/g'

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.