Replace work in line by combining after grep

Viewed 80

I need to replace a word after performing a grep and getting the last line of the result.

Here my example file:

aaa ts1 ts2
bbb ts3 ts4
aaa ts5 ts6
aaa ts7 NONE

What I need is to select all lines containing 'aaa', get the last one in the result and replace NONE.

I tried

cat <file> | grep "aaa" | tail -n 1 | sed -i 's/NONE/ts8/g'

but it doesn't work.

Any suggestion to do that?

Thanks

3 Answers

With tac + awk solution please try following.

tac Input_file | awk '/aaa/ && ++count==1{sub(/NONE/,"ts8")} 1' | tac

once you are happy with above command try following, to do inplace save into Input_file.

tac Input_file | awk '/aaa/ && ++count==1{sub(/NONE/,"ts8")} 1' | tac > temp && mv temp Input_file

Explanation: Firstly printing Input_file in reverse order by tac then sending its standard output to awk as an input where substituting of NONE to ts8 in very first line(which is actually last line containing aaa). Simply printing all other lines, again sending output to tac to make it in actual order like Input_file's order.

For doing this in a single command, this should work in any version of awk:

awk 'FNR==NR {if ($1=="aaa") n=FNR; next} FNR == n {$3="TS7"} 1' file{,}

aaa ts1 ts2
bbb ts3 ts4
aaa ts5 ts6
aaa ts7 TS7

To save output in same file use:

awk 'FNR==NR {if ($1=="aaa") n=FNR; next}
FNR == n {$3="TS7"} 1' file{,} > file.out && mv file.out file

Or using gnu sed, you may use:

sed -i -Ez 's/(.*\naaa[[:blank:]]+[^[:blank:]]+[[:blank:]]+)NONE/\1ts8/' file

cat file

aaa ts1 ts2
bbb ts3 ts4
aaa ts5 ts6
aaa ts7 ts8

If you want to get the last line that matches aaa at the start, you can go through all lines, and in the END block, print the last occurrence and replace NONE with ts8 using awk:

awk '$1=="aaa"{last=$0}END{sub(/NONE/,"ts8",last);print last}' file

In parts:

$1=="aaa" {               # If the first field is aaa
  last=$0                 # Set variable last to the whole line (overwrite on each match)
}
END {                     # Run once at the end                
  sub(/NONE/,"ts8",last)  # Replace NONE with ts8 in the last variable
  print last                 
}
' file

Output

aaa ts7 ts8
Related