4

This post explains how to add a line at the beginning of a file from the terminal. But how do I modify from the terminal a line somewhere in a file if I do not know which line it is?

I should modify the line eni=10.*10**9 to eni=10.*10**8 note the exponents. It is the second time that eni appears

Kulfy
  • 17,696
mattiav27
  • 875

3 Answers3

4

I think this is what you want:

line=$(grep -n -m2 "eni" file | tail -n1 | cut -f1 -d:)

sed -i $line's/9$/8/' file
  • @wjandrea modified the answer, take a look. – schrodingerscatcuriosity Sep 01 '19 at 19:07
  • 2
    Nice! You could simplify getting the line number: line="$(awk '/eni/ {count+=1;if(count==2){print NR}}' test.txt)" – wjandrea Sep 01 '19 at 19:13
  • 1
    This answer will match the second occurrence of eni and return the line number. Then it will change the last occurrence of 9 with 8 in that line. If more than one 9 are present in the same line, it will only change the last one and might miss the intended one. – Raffa Sep 01 '19 at 20:22
  • 1
    @Raffa Yes, a more elaborate regex could be done, but OP's data doesn't show more text after the line, that's why I chose to simplify it to match what OP shows as a line. Note that OP wrote "I should modify the line", not x content in the line. – schrodingerscatcuriosity Sep 01 '19 at 20:29
  • 1
    @guillermochamorro You did a good job, but I however recommend you add such explanation to your answer as it could prevent unintended modification to the file. Thank you – Raffa Sep 01 '19 at 20:33
4

Since Ubuntu now ships with GNU Awk v4.0+ (which provides an inplace module) you could do something like

gawk -i inplace '/eni=/ {if (++c == 2) sub(/10\*\*9/,"10**8")} 1' file

You can make the regular expressions /eni=/ and/or /10\*\*9/ more or less specific as required.

Similarly in perl

perl -i -pe 'if (/eni=/) {s/10\*\*9/10\*\*8/ if (++$c == 2)}' file
steeldriver
  • 136,215
  • 21
  • 243
  • 336
3

Using sed:

sed -i ': 1 ; N ; $!b1 ; s/eni\=10\.\*10\*\*9/eni\=10\.\*10\*\*8/2' filename

/ is one of the delimiters and \ is the escape character. \ is used so that bash won't interpret special characters as some command, like * as wildcard.

Kulfy
  • 17,696
  • This answer will match the second occurrence of eni=10.*10**9 in a new line and will change it with eni=10.*10**8. Run it only once. – Raffa Sep 01 '19 at 20:22