0

My input file has some text that needs to be changed. It has a couple of possibilities for example;

CONSTANT change/me !KEY2 !KEY3
CONSTANT change/me 
CONSTANT change/me !DIFFERENTKEY

There is always a constant key (i.e. CONSTANT) that doesn't change. There is also the possibilities of different keywords after the text that needs to be replaced. These are indicated with an exclamation mark (!) and there may be no other keywords or thousands. I am only interested in replacing the text after CONSTANT and any possible keys starting with !. Preferably using sed.

The following is my expected output. change/me in input has to be replaced with changed;

CONSTANT changed !KEY2 !KEY3
CONSTANT changed 
CONSTANT changed !DIFFERENTKEY

I have tried different things found in answers (here and here, here) on SO but I can't seem to figure it out. This closest I came was from this link.

sed -r 's/(^CONSTANT) (.+?) (\!.*$)/\1 changed \3/g' input

Which results in;

CONSTANT changed !KEY2
CONSTANT change/me
CONSTANT changed !DIFFERENTKEY

I tried different combinations but at this point it feels like I just shooting in the dark.

Conditions:

  • CONSTANT doesn't change
  • change/me is arbitrary text could also be blahblah that needs to be replaced
  • A !KEY doesn't have to be present
  • A !KEY can be present and can be multiple of them, but always separated with space. I want to maintain CONSTANT and any possible !KEYs.
tstev
  • 607
  • 1
  • 10
  • 20

2 Answers2

1

The third (\!*.*$) is forced to start with !, and the line 2 does not match.

Note that (.+?) (\! ... makes sed search for the longest sequence for (.+?) up to a !..., that is why !KEY2 is lost.

Mandatory: the change/me never contains !, for the solution below to work.

Give a try to this:

sed -r 's/(^CONSTANT) ([^!]+?) *(\!.*|.*)$/\1 changed \3/g' input

Output

CONSTANT changed !KEY2 !KEY3
CONSTANT changed 
CONSTANT changed !DIFFERENTKEY
Jay jargot
  • 2,745
  • 1
  • 11
  • 14
1

Don't bother handling the full line, whether additional content appears after the text to change doesn't matter :

sed 's@^CONSTANT change/me@CONSTANT changed@'

I used @ as a separator instead of the usual / in order to avoid having to escape the / in change/me.

You can try it here.

If the change/me text varies but never contains spaces, you can use the following instead :

sed -E 's@^CONSTANT [^ ]+@CONSTANT changed@'

(for older versions of GNU sed you will want to use the -r flag instead of -E)

You can try it here.

Aaron
  • 24,009
  • 2
  • 33
  • 57
  • `change/me` was just a random text. it could also have been `pleasechange` or `blahblah`. – tstev Dec 14 '18 at 13:49
  • @tstev Yeah, I ended up getting this ; what about the second solution that will replace the sequence of non-space characters that follows `CONSTANT`? – Aaron Dec 14 '18 at 13:50
  • This seems to work and I maintain my `!KEY` s. Thanks! – tstev Dec 14 '18 at 14:03
  • The `@` tip is also useful just incase i need to change it to a different absolute path. – tstev Dec 14 '18 at 14:06