0

I have file which contains lines like below. Wanted to replace the words in quotes after -s and -e. Tried with sed but didn't work.

File Contents

abc -s "today" -e "today" def
abc -s "yesterday" -e "yesterday" def
abc -s "3 days ago" -e "3 days ago" def

Tried Command

sed 's|-s "*" -e "*"|-s "1" -e "2"|g' <filename>

Required output

abc -s "1" -e "2" def
abc -s "1" -e "2" def
abc -s "1" -e "2" def
0

2 Answers 2

2

The main issue with your own attempt is that "*" means "match zero or more double quotes, followed by yet another double quote". This is because * is a regular expression modifier that means "zero or more of the previous expression". This means that "*" would match strings like ", "", """ etc.

Apart from that, you needlessly use a different delimiter for the s/// command, and you use /g at the end even though you do not expect to do more than one replacement per line. But these are just issues relating to style.


There are several ways to do this with sed, but all of them must match a string between double quotes in one way or another. A string between double quotes can be match by the regular expression "[^"]*", i.e. "match a double quote, and then zero or more characters that are not double quotes, followed by another double quote character".

$ sed -e 's/-s "[^"]*"/-s "1"/' -e 's/-e "[^"]*"/-e "2"/' file
abc -s "1" -e "2" def
abc -s "1" -e "2" def
abc -s "1" -e "2" def

The above uses two separate expressions to match and replace the strings after the given option, which also means that

  • it doesn't matter in which order the options are given in the input (-s "whatever" will always be replaced by -s "1" and -e "whatever" will always be replaced by -e "2"),
  • it makes it indifferent to the number of spaces between the options (change e.g. -s "[^"]*" to -s *"[^"]*" to also allow multiple spaces between the option and the option argument),
  • it doesn't matter whether or not there may be other options present (nor how these are ordered in relation to the -s and -e options), and
  • if only one of -s and -e is present, but not the other, the option and the option-argument present would be replaced.

If you additionally need to do the replacements only on lines that start with abc:

sed -e '/^abc/{' -e 's/-s "[^"]*"/-s "1"/' -e 's/-e "[^"]*"/-e "2"/' -e '}' file

or without all those -e options in the sed command:

sed '/^abc/{ s/-s "[^"]*"/-s "1"/; s/-e "[^"]*"/-e "2"/; }' file

Change /^abc/ to /^abc.*def$/ if you additionally need to make sure that the lines you modify ends with def.

2
  • Thanks for your detailed explanation
    – upkar
    May 7, 2020 at 11:48
  • Today i have come across new scenario, where instead of double quotes i got contents with single quotes. I have tried with above example i didnt get the output. I tried solution as per stackoverflow.com/questions/52723293/… by using '(.*)' but vain, shall i post that as a new question. please suggest.
    – upkar
    Jun 3, 2020 at 1:57
1

Sed uses regular expressions, not wildcard patterns. * means "repeat the preceding element zero or more times", and you need to repeat . which means "anything":

sed 's/-s ".*" -e ".*"/-s "1" -e "2"/'
2
  • could you please check i didnt get he output
    – upkar
    May 7, 2020 at 10:43
  • @upkar: Sorry, a missing *.
    – choroba
    May 7, 2020 at 11:28

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.