1

I have a problem with sed unable to correctly capture the \1 capture group in the below example:

echo '//apple' | sed "s/^\(\/\)\{0,2\}apple\(\/\)\?/\1banana\2/"
                         -------------              --
                            ^                        ^
                            |                        |__ writing back what it captured
                            |
                            |_ this is the capture group that I have problem capturing

I expected the output of: //banana correctly capturing the //. How can I make sed to correctly the \1 capture group?

2
  • 1
    You only captured one / Commented Mar 11, 2022 at 15:43
  • 2
    With alternate delimiter use cleaner sed: sed -E 's~(/{0,2})apple(/{0,2})~\1banana\2~'
    – anubhava
    Commented Mar 11, 2022 at 15:45

2 Answers 2

2

You only captured one /.

You need to use

echo '//apple' | sed 's/^\(\/\{0,2\}\)apple\(\/\)\?/\1banana\2/' # POSIX BRE
echo '//apple' | sed -E 's~^(/{0,2})apple(/)?~\1banana\2~'       # POSIX ERE variant

See the online demo. The POSIX BRE pattern matches

  • ^ - start of string
  • \(\/\{0,2\}\) - Group 1: zero, one or two occurrences of a / char
  • apple - a fixed string
  • \(\/\)\? - an optional Group 2 matchong a / char.

Note you do not need to escape capturing parentheses, nor ? and {min,max} quantifiers when using POSIX ERE regex that is enabled with the -E option.

You need not escape / chars in the sed command when / is not used as a regex delimiter char.

Also, see this regex graph:

enter image description here

1
  • 1
    Thank you for the tip on -E I will use this option from now on.
    – daparic
    Commented Mar 12, 2022 at 11:51
1

With an alternate delimiter and -E use cleaner and easier to read:

echo '//apple' | sed -E 's~^(/{0,2})apple(/{0,2})~\1banana\2~'
4
  • Thanks. But yours is missing the needed ^, otherwise it won't work.
    – daparic
    Commented Mar 11, 2022 at 16:06
  • If option -E is not working, try to use -r instead. Furthermore: I think your sed statemet could be shortened to sed 's|\w\+|banana|' or sed 's|[^/]\+|banana|'. Commented Mar 11, 2022 at 16:18
  • @eigenfield: Yes I missed anchor (edited it now)
    – anubhava
    Commented Mar 11, 2022 at 16:22
  • @KrischaOnarestlessday Negative, without the very important {a, b} constraint.
    – daparic
    Commented Mar 12, 2022 at 11:49

Not the answer you're looking for? Browse other questions tagged or ask your own question.