Search code examples
regexbashsedpattern-matchingposix

Match and Replace ![foo](/bar/) with Regex in SED


I'm trying to write a RegEx for SED to make it match and replace the following MarkDown text:

![something](/uploads/somethingelse)

with:

![something](uploads/somethingelse)

Now, in PCRE the matching pattern would be:

([\!]|^)(\[.*\])(\(\/bar[\/])

as tested on Regex101:

enter image description here

but on SED it's invalid.

I've tried a lot of combinations before asking, but I'm going crazy since I'm not a RegEx expert.

Which is the right SED regex to match and split that string in order to make the replacement with sed as described here?


Solution

  • The sed command you need should be run with the -E option as your regex is POSIX ERE compliant. That is, the capturing parentheses should be unescaped, and literal parentheses must be escaped (as in PCRE).

    You may use

    sed -E 's;(!\[.*])(\(/uploads/);\1(uploads/;g'
    

    Details

    • (!\[.*]) - Capturing group 1:
      • ! - a ! char (if you use "...", you need to escape it)
      • \[.*] - a [, then any 0+ chars and then ]
    • (\(/uploads/) - Capturing group 2:
      • \( - a ( char
      • /uploads/ - an /uploads/ substring.

    The POSIX BRE compliant pattern (the actual "quick fix" of your current pattern) will look like

    sed 's;\(!\|^\)\(\[.*](\)/\(uploads/\);\1\2\3;g'
    

    Note that the \(...\) define capturing groups, ( matches a literal (, and \| defines an alternation operator.

    Details

    • \(!\|^\) - Capturing group 1: ! or start of string
    • \(\[.*](\) - Capturing group 2: a [, then 0+ chars, and then (
    • / - a / char
    • \(uploads/\) - Capturing group 3: uploads/ substring

    See the online sed demo

    The ; regex delimiter helps eliminate escaping \ chars before / and make the pattern more readable.