Pedro Gonzalez
Pedro Gonzalez

Reputation: 95

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?

Upvotes: 1

Views: 117

Answers (1)

Sundeep
Sundeep

Reputation: 23677

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.

Upvotes: 1

Related Questions