1

My sed expression looks as belos:

sed -i "s/-D CONSOLELOG /-D CONSOLELOG  -fPIC /g" makefile.init

makefile.init

 CFLAGS = -std=c99 -rdynamic -g -Wall -Wno-write-strings -D CONSOLELOG  

Output after 1st Run( As expected)

CFLAGS = -std=c99 -rdynamic -g -Wall -Wno-write-strings -D CONSOLELOG  -fPIC

2nd Run (Notice the extra fPIC at the end)

CFLAGS = -std=c99 -rdynamic -g -Wall -Wno-write-strings -D CONSOLELOG  -fPIC -fPIC

I need to modify my sed expression to get output as in (1) irrespective of the number of times it is executed

Zaks
  • 668
  • 1
  • 8
  • 30

2 Answers2

3

This might work for you (GNU sed):

sed -ri 's/-D CONSOLELOG (-fPIC )?$/&-fPIC /' file

This would insert at most 2 -fPIC options following a -D CONSOLELOG option.

potong
  • 55,640
  • 6
  • 51
  • 83
2

Sample changed for illustration purposes

$ cat ip.txt 
42 foo baz 
ijk baz xyz
$ sed -i 's/baz $/&123/' ip.txt
$ cat ip.txt
42 foo baz 123
ijk baz xyz

$ # further runs won't change input
$ sed -i 's/baz $/&123/' ip.txt
$ cat ip.txt
42 foo baz 123
ijk baz xyz
  • $ is a meta character to ensure matching only at end of line
  • so, matches elsewhere in the line won't be changed and hence applying the command again won't result in duplication
  • & in replacement section is backreference to entire matched string in search section
  • since there can only be one match at end of line, g modifier is not needed


To replace anywhere in the line(assuming only single match per line)

$ cat ip.txt 
42 foo baz 
ijk baz xyz
$ sed -i '/baz 123/! s/baz /&123/' ip.txt
$ cat ip.txt
42 foo baz 123
ijk baz 123xyz

$ # further runs won't change input
$ sed -i '/baz 123/! s/baz /&123/' ip.txt
$ cat ip.txt
42 foo baz 123
ijk baz 123xyz
  • sed commands can be qualified with addressing
  • here, /baz 123/! means lines not matching baz 123


Further reading: Difference between single and double quotes in Bash

Sundeep
  • 23,246
  • 2
  • 28
  • 103