问题
I am trying to extract a code block from a Markdown document using PCRE RegEx. For the uninitiated, a code block in Markdown is defined thus:
To produce a code block in Markdown, simply indent every line of the block by at least 4 spaces or 1 tab. A code block continues until it reaches a line that is not indented (or the end of the article).
So, given this text:
This is a code block:
I need capturing along with
this line
This is a code fence below (to be ignored):
``` json
This must have three backticks
flanking it
```
I love `inline code` too but don't capture
and one more short code block:
Capture me
So far I have this RegEx:
(?:[ ]{4,}|\t{1,})(.+)
But it simply captures each line prefixed with at least four spaces or one tab. It doesn't capture the whole block.
What I need help with is how to set the condition to capture everything after 4 spaces or 1 tab until you either get to a line that is not indented or the end of the text.
Here's an online work in progress:
https://www.regex101.com/r/yMQCIG/5
回答1:
You should use begin/end-of-string markers (^ and $ in combination with the m modifier). Also, your test text had only 3 leading spaces in the final block:
^((?:(?:[ ]{4}|\t).*(\R|$))+)
With \R and the repetition you match one whole block with each single match, instead of a line per match.
See demo on regex101
Disclaimer: The rules of markdown are more complicated than the presented example text shows. For instance, when (nested) lists have code blocks in them, these need to be prefixed with 8, 12 or more spaces. Regular expressions are not suitable to identify such code blocks, or other code blocks embedded in markdown notation that uses the wider range of format combinations.
回答2:
Try this?
[a-z]*\n[\s\S]*?\n
It will extract from your example
This must have three backticks
flanking it
回答3:
There are 3 ways to highlight code: 1) using start-of-line indentation 2) using 3 or more backticks enclosing a multiline block of code or 3) inline code.
1 and 3 are part of John Gruber original Markdown specification.
Here is the way to achieve this. You need to perform 3 separate regexp tests:
Using indentation
(?:\n{2,}|\A) # Starting at beginning of string or with 2 new lines (?<code_all> (?: (?<code_prefix> # Lines must start with a tab or a tab-width of spaces [ ]{4} | \t ) (?<code_content>.*\n+) # with some content, possibly nothing followed by a new line )+ ) (?<code_after> (?=^[ ]{0,4}\S) # Lookahead for non-space at line-start | \Z # or end of doc )
2a) Using code block with backticks (vanilla markdown)
(?:\n+|\A)? # Necessarily at the begining of a new line or start of string
(?<code_all>
(?<code_start>
[ ]{0,3} # Possibly up to 3 leading spaces
\`{3,} # 3 code marks (backticks) or more
)
\n+
(?<code_content>.*?) # enclosed content
\n+
(?<!`)
\g{code_start} # balanced closing block marks
(?!`)
[ \t]* # possibly followed by some space
\n
)
(?<code_trailing_new_line>\n|\Z) # and a new line or end of string
2b) Using code block with backticks with some class specifier (extended markdown)
(?:\n+|\A)? # Necessarily at the beginning of a new line
(?<code_all>
(?<code_start>
[ ]{0,3} # Possibly up to 3 leading spaces
\`{3,} # 3 code marks (backticks) or more
)
[ \t]* # Possibly some spaces or tab
(?:
(?:
(?<code_class>[\w\-\.]+) # or a code class like html, ruby, perl
(?:
[ \t]*
\{(?<code_def>[^\}]+)\} # a definition block like {.class#id}
)? # Possibly followed by class and id definition in curly braces
)
|
(?:
[ \t]*
\{(?<code_def>[^\}]+)\} # a definition block like {.class#id}
) # Followed by class and id definition in curly braces
)
\n+
(?<code_content>.*?) # enclosed content
\n+
(?<!`)
\g{code_start} # balanced closing block marks
(?!`)
)
(?:\n|\Z) # and a new line or end of string
Using 1 or more backticks for inline code
(?:\n{2,}|\A) # Starting at beginning of string or with 2 new lines (?<code_all> (?: (?<code_prefix> # Lines must start with a tab or a tab-width of spaces [ ]{4} | \t ) (?<code_content>.*\n+) # with some content, possibly nothing followed by a new line )+ ) (?<code_after> (?=^[ ]{0,4}\S) # Lookahead for non-space at line-start | \Z # or end of doc )
来源:https://stackoverflow.com/questions/41351903/how-can-i-match-a-markdown-code-block-with-regex