How can I grep for every uneven match?

Viewed 70

Markdowns fenced code blocks look like this

```
Here is the code
in many lines
```

or like this:

```text
Here is the code
in many lines
```

The "text" specifies the language which should be used for highlighting.

I want to run over a flat directory and find all files which contain fenced code blocks without a specified language. How can I find fenced code blocks without a specified language?

What I tried

The following is a superset of what I want:

$ grep -rIE -m1 "\`\`\`[[:space:]]*$" *

The problem is the closing part. Essentially this finds all files which have a fenced code block at all. But how do I grep for every uneven triple backtick?

My guess is that I have to grep for the complete code block. It is guaranteed that there is either a newline after the triple backticks or a language.

So I tried the following two:

grep -rIzPo -m1 "\`\`\`\\n(.*?)\`\`\`" *
grep -rIzEo -m1 "\`\`\`\\n(.*?)\`\`\`" *

It found a couple of cases, but it missed at least one. I have no idea why.

Problem: Two codeblocks

I have many files with multiple code blocks, e.g:

```python
a = "Hello"
b = "Stackoverflow"

print(f"{a} {b}")
```

and

```python
    print("foobar")
```

Please note that I don't want a file with this content to match! All regexes I tried so far match

```

and

```python
    print("foobar")
```
1 Answers

I think that'd be easier with .

awk 'BEGINFILE{f=0} /^```/{f=!f}
     f&&/^```\s*$/{print FILENAME;nextfile}' *

f denotes whether last match was even or uneven. It is reset at the beginning of each file, and negated by each match. When f is 1 and exit condition (i.e current line is three backquotes followed by zero+ spaces) is met, the program prints filename and moves on to the next file.

Related