1

I have the following in my config.txt file.

some text
firmware_version 12.3
some more text ...

The sed -i 's/^firmware_version .*/firmware_version 12.4/' /config.txt command replaces the firmware version but what I'd like to be able to do is that even if sed doesn't find a line occurrence of "firmware_version .*" it still adds the new replacement.

In other words if my config.txt file includes the following:

some text
some more text ...

I'd still like the end result to be

some text
firmware_version 12.4
some more text ...

I just want to come up with a universal one line command for this.

Thanks!

sylvian
  • 649
  • 1
  • 8
  • 17
  • Should it detect 'some text' or 'some more text' as the match with no 'firmware_version' in between? Or can 'firmware_version' go at the end if the 'firmware_version' is not found? Spotting that the firmware version is missing between two lines is probably harder than adding it at the end, though neither is entirely straight-forward. Could there be other lines between 'some text' and 'some more text' than just 'firmware_version'? – Jonathan Leffler Apr 01 '14 at 20:46
  • 'firmware_version' can go to the end if it's not found, and the config file can be completely empty too, so there might be nothing in the config file and 'firmware_version' should still be added if that command is executed. – sylvian Apr 01 '14 at 20:49

3 Answers3

2

Thanks for your responses

I was really looking for an easier and simpler solution and I would expect sed to return a different exit status when the searched text doesn't match and then I could decide what to do next.

There are some discussions on how to make sed return a specific code if it doesn't match a criteria, but I couldn't make it work and the manual doesn't mention anything about it (or I may have missed something)

After a little more research I found not a very neat but an acceptable solution.

grep -q '^firmware_version .*' /config.txt && sed -i 's/^firmware_version .*/firmware_version 12.4/' /config.txt || echo 'firmware_version 12.4' >> /config.txt

So if grep finds a match then we run the sed command otherwise we echo the 'firmware_version 12.4' text to config.txt

Community
  • 1
  • 1
sylvian
  • 649
  • 1
  • 8
  • 17
0

awk solution:

awk '/some text/,/some more text/{if (index($0, "firmware_version")) {$0="firmware_version 12.4"; p=1; next}} !p{sub(/$/, "\nfirmware_version 12.4"); p=1} 1' file

Which gives this output:

some text
firmware_version 12.4
some more text ...

For both input files:

some text
firmware_version 12.3
some more text ...

and this one:

some text
some more text ...
anubhava
  • 713,503
  • 59
  • 514
  • 593
0

For non-empty files, this works. It's a different model, though. If the 'firmware_version' appears between 'some text' and 'some more text' then delete it. When you come across 'some more text', insert the firmware version. It's tricky enough that I put the editing commands into a file named (unoriginally) sed.script:

/some text/,/some more text/{
/firmware_version .*/d
/some more text/i\
firmware_version 12.4
}

Then, given config-1.txt:

some text
firmware_version 12.3
some more text

and config-2.txt:

some text
some more text

you can run the script like:

sed -f sed.script config-1.txt

and it produces the same output for both inputs:

some text
firmware_version 12.4
some more text

If the input file is empty, I think it is best handled separately. This shell script fragment writes the new file to standard output:

if [ -s ${config_file} ]
then sed -f sed.script ${config_file}
else echo "firmware_version 12.4"
fi

If you want to overwrite the original file and your sed supports -i.bak, then:

if [ -s ${config_file} ]
then sed -i.bak -f sed.script       ${config_file}
else echo "firmware_version 12.4" > ${config_file}
fi
Jonathan Leffler
  • 698,132
  • 130
  • 858
  • 1,229