Search code examples
sedbackticks

sed ignoring triple backticks


I want to replace

```javascript
something
```

with

{code}javascript
something
{code}

Now, when i run sed on a file with javascript something(everything in the same line, no new lines)

sed -e 's/```\(.*\)```/{code}\1{code}/' sedfile

It outputs what I want: {code}javascript a23231 {code} But when I run sed with a file that has new lines accounted for, it doesnt do it properly. I tried to espace backticks with \ but it wasnt output I wanted.

What am I doing wrong?


Solution

  • By default sed operates only one line at a time (based on newline character). There are ways to change that, but perl would be better suited if you can have multiple matches in single line (non-greedy matching)

    $ cat ip.txt
    foo ```xyz``` baz ```javascript 123```
    
    ```javascript
    something
    ```
    
    $ perl -0777 -pe 's/```(.*?)```/{code}$1\{code}/gs' ip.txt
    foo {code}xyz{code} baz {code}javascript 123{code}
    
    {code}javascript
    something
    {code}
    
    • -0777 to slurp entire input file as a single string
    • ```(.*?)``` will match the backtick snippets as minimally as possible
    • {code}$1\{code} desired replacement, $1 will have the text matched by the capture group
      • for some reason, {} is causing issue in replacement section, which is why the second { is escaped. I think it is causing conflict with hash syntax
    • s flag is needed to allow . to match newline character as well
    • Use -i option if you need in-place editing

    With sed if -z option is available and content between the triple backticks cannot have backtick:

    $ sed -zE 's/```([^`]+)```/{code}\1{code}/g' ip.txt
    foo {code}xyz{code} baz {code}javascript 123{code}
    
    {code}javascript
    something
    {code}
    

    The -z option causes sed to use ASCII NUL as the separator instead of newline character. If input file has NUL character, this solution will not work.

    Edit: Just realized that a simple sed 's/```/{code}/g' ip.txt may also work if the input is well formed like the example used here.