Score:1

How to replace strings in the last n-lines of multiple files in linux

vu flag

How can I replace strings in lets say 'last 10 lines' of multiple files?

I have about 100 files with the same extension '.txt' and I would like to replace string 'GLN' to 'LOO' in the last 10 lines of each file. How do I do this? I know how to do it for one file but not for several files. When I use this command ;

for i in `head -3 *.txt  | awk '{print $4}'`
     do
                   sed -i 's/GLN/LOO/g' *.txt 
     done

It replaces GLN everywhere it appears in the files and not just the last 10 lines. Please, what am I doing wrong?

Score:2
hr flag

It's not clear what head -3 *.txt | awk '{print $4}' returns here since you haven't shown us a sample of your file(s), however sed -i 's/GLN/LOO/g' *.txt will replace all of the instances of GLN in all the lines in all the files matching *.txt, provided the loop executes at least once.

AFAIK there's no direct way to address the last n lines of a file in sed - so to use that, you would need to calculate the offset externally, using wc -l and shell arithmetic for example:

for f in *.txt; do 
  start=$(( $(wc -l <"$f") - 9 ))
  sed "$start"',$s/GLN/LOO/g' "$f"
done

(I removed the -i so output goes to the terminal, for testing). You could use something like awk 'END{print NR-9}' "$f" in place of $(( $(wc -l <"$f") - 9 )) to get the start offset if your intention was to use awk.

Alternatively you could use tac to invert the file and make replacements in the first n lines, then tac the result - although that makes in-place replacement complicated.

In this situation I would probably reach for ed or ex which do support numerical address offsets ex. testing with output to the terminal:

for f in *.txt; do 
  printf '%s\n' '$-9,$s/GLN/LOO/g' ',p' | ed -s "$f"
done

Once you are happy that it's doing the right thing, change ,p to wq to write the result to the file (equivalent of sed's -i).

Score:1
cn flag

I would use tac and awk functions for this job as follows:

tac file1.txt | awk 'NR<11 {gsub("GLN","LOO")};{print}' | tac
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.