This is more of a architectural question:

I have a script that does some in file sed replacements/additions like:

sed -i 's/MY_VAR = 1000/MY_VAR = 1000\nMY_VAR2 = 500/' file.txt

which works fine but this is part of a fairly large script and someone may either ^C the first run and re-run this or just re-run it N-times back-to-back which will result in something like

MY_VAR = 1000
MY_VAR2 = 500
MY_VAR2 = 500
MY_VAR2 = 500
MY_VAR2 = 500

which might not be expected. So my question is: what's the best way to avoid this? I came up with something like:

if [ ! -f file.txt~copy ]
    cp file.txt file.txt~copy
    sed -i 's/MY_VAR = 1000/MY_VAR = 1000\nMY_VAR2 = 500/' file.txt

which should work fine but I was wondering if there's a better/recommended way to go about it? The above could obviously be problematic if your files are significantly large and you may just want to touch a copy file for protection instead.

  • If you're worried about this not being idempotent then perhaps you could write your changes to a different file than the source, leaving the source untouched. Another option might be to have a guard (or token) in the changed file - if the guard exists then the file has already been modified – roaima Jun 12 at 20:52

This will not easily scale and hence may or may not be a good fit for your real use case, but you may check whether the line you are going to add is already there and only add it if it is not:

sed '
  /^MY_VAR = 1000$/ {
    $ b a
    /\nMY_VAR2 = 500$/! s/\n/&MY_VAR2 = 500\
    :a a \
MY_VAR2 = 500

Here, when the exact line MY_VAR = 1000 is found:

  • if it is the last ($) line, we branch to the a label and append MY_VAR2 = 500 at the end of the output;

  • if the pattern space, after appending the Next line to it, does not (!) end in a newline followed by MY_VAR2 = 500, its embedded newline is replaced with a newline + MY_VAR2 = 500 + a newline; (we then branch to the end of the script to avoid running the append command too);

  • otherwise, we do nothing.

  • Wow, this is some crazy stuff, for me anyways! Thanks! :D – r713.250 Jun 12 at 21:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.