0

Is there a more simple way to do the following below? Maybe a single command that will replace the text if it exists, if not append text to the file. I need to do this for various files and want to find a way to put in in a function. the line formatting will vary slightly between, I put 2 example below.

#If grep exists then sed line, else echo to end of file
grep -q '^sometext' /file1.txt && sed -i "" "s/^sometext.*/sometext $newvar/" /file1.txt || echo "sometext $newvar" >> /file1.txt
grep -q '^someothertext' /file2.txt && sed -i "" "s/^someothertext.*/someothertext=$othernewvar/" /file1.txt || echo "someothertext=$othernewvar" >> /file1.txt
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
bc81
  • 177
  • 2
  • 10
  • Would it ever be possible to make *more* than one replacement? I think it should be possible in `sed` to write a script that contains both the replacement code *and* the append code, but the append code is only reached if no replacement occurs. – chepner May 15 '17 at 15:39

1 Answers1

1

Whenever you find yourself using grep+sed or multiple seds or various other combinations of tools just to manipulate text, it's time to consider simply using awk instead:

awk -v key="sometext" -v sep=" " -v new="$newvar" '
sub("^"key".*",key sep new) { f=1 }
{ print }
END { if (!f) print key sep new }
' file

awk -v key="someothertext" -v sep="=" -v new="$othernewvar" '
sub("^"key".*",key sep new) { f=1 }
{ print }
END { if (!f) print key sep new }
' file

Note that the above use regexps and backreference-enabled replacement strings just like sed does so you'd have to worry about escaping metacharacters (., *, ?, +, &, etc. - see https://stackoverflow.com/a/29626460/1745001) in the key and new text. Since you're using awk, though, you can use literal strings instead:

awk -v key="sometext" -v sep=" " -v new="$newvar" '
index(key)==1 { $0 = key sep new; f=1 }
{ print }
END { if (!f) print key sep new }
' file

and then you don't have to worry about that. The only character you DO still have to think about with the above is backslash because \t will be translated to a tab character, etc. when doing a variable assignment with -v but there's a simple tweak for that if it's an issue.

Community
  • 1
  • 1
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • 1
    had to remove `key` from the output but other than that this is what i needed, thanks! – bc81 May 16 '17 at 00:34