Harshu
Harshu

Reputation: 91

sed substitution - do not modify for a particular case

I have a file with many lines written like this -

random text
some info, command -task shoot and more info
some info, command -new_task shoot and more info
more info and shoot a lot
command -task shoot and some more info and shoot a lot

I want the first letter of shoot to be capital except for the case command -* shoot.

So after substitution my file should look like this -

random text
some info, command -task shoot and more info
some info, command -new_task shoot and more info
more info and Shoot a lot
command -task shoot and some more info and Shoot a lot

I have written the following script for this -

var="shoot";
sed -i "/-.*?${var}/ ! s/ ${var} / ${var^} /g" file;

This script works fine except for the case when command -* shoot and shoot are written in the same line. In this case I get the output as -

command -task Shoot and some more info and Shoot a lot

Both the shoot becomes capital in this case which is undesirable. Is there any way I can solve this problem?

Upvotes: 1

Views: 49

Answers (1)

dash-o
dash-o

Reputation: 14432

The task seems to require some form of look-back, where each replacement is conditional on the previous two tokens (which must NOT match 'command -*'). As indicated above, simple global replacement on a single condition will not work for cases like

command -task shoot and some more info and shoot a lot

Given sed relatively strict flow, and lack of complex condition, variables, might be easier to leverage sed pipeline, and build this as a series of commands:

  1. Encode each 'command -* shoot' to hide them from next step substitution
  2. Global replace of remaining shoot (surrounded with spaces)
  3. Restore the 'hidden' shoorts.
sed -e 's/\(command -[^ ]\+ \)shoot /\1@shoot /' -e 's/ shoot / Shoot /' -e 's/ @shoot / shoot /'

The 'hiding' is achieved by insert a @ before the shoot.

The pattern for the command option (-*) can be adjusted for more restricted character set

Possible to combine the 3 '-e' into single script, and use extended RE, as per Jotne suggestion to simplify command:

sed -r 's/(command -[^ ]+ )shoot /\1@shoot /;s/ shoot / Shoot /;s/ @shoot / shoot /'

Upvotes: 2

Related Questions