How can I edit the last n lines in a file?

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.

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

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).