我有一个我想要解析的字符串,看起来有点像github markdown,但我真的不想完全实现。该字符串将是“代码”块和“文本”块的混合。代码块将是三个反引号,然后是可选的“语言”,然后是一些代码,最后是三个反引号。非代码将是其他所有内容。我不(但可能应该)关心用户是否无法在“文本”块中输入三个反引号。这是一个例子......
This is some text followed by a code block ```ruby def function "hello" end ``` Some more text
当然可能会有更多代码和文本块穿插。我已经尝试为此写一个正则表达式,它似乎工作,但我无法得到组(在parens)给我所有的匹配和扫描()失去了排序。我已经看过使用几个红宝石解析器(树梢,手镯),但看起来有点大我想要的东西,但如果那是我最好的选择,我愿意走那条路。
思想?
有几个人要求我正在尝试的RE(下面的许多变化)......
re =
/
```\s*\w+\s* # 3 backticks followed by the language
(?!```).*? # The code everything that's not 3 backticks
``` # 3 more backticks
| # OR
(?!```).* # Some text that doesn't include 3 backticks
/x # Ignore white space in RE
似乎即使在简单的情况下,例如
md = /(a|b)*/.match("abaaabaa")
我无法获得所有的a和b。从md [3]说不存在。希望这更有意义,这就是为什么我不认为RE会在我的情况下起作用,但我不介意被证明是错误的。
答案 0 :(得分:1)
我将在这里做一些假设,基于我对Markdown(github,stackoverflow-flavors)的知识和你的问题(对于文本的其余部分不是很精确)。
1。 每个代码块以奇异行开始, 只包括三个反引号,一个可选的 language-name和newline-char。
2。 每个代码块仅以奇数行结束 包含三个反引号。
3。 代码块不为空。
如果您可以接受这些假设,则以下代码应该有效
(假设文本在str
变量中):
regex = %r{
^```[[:blank:]]*(?<lang>\w+)?[[:blank:]]*\n # matches start of codeblock, and captures optional :lang.
(?<content>.+?) # matches codeblock content and captures in :content
\n[[:blank:]]*```[[:blank:]]*\n # matches ending of codeblock.
}xm # free-space mode and . matches newline.
position = 0
matches = []
while(match = regex.match(str,position)) do
position = match.end 0
matches << [match[:lang], match[:content]]
end
此匹配后包含一个数组数组,其中一个内部数组表示匹配 第一个元素是(可选)语言,可以是nil,第二个元素 是内容。
如果您对文本有更多假设,我可以改变正则表达式。
这是我使用的测试字符串:
str = %{
this is some random text.
```ruby
def print
puts "this is a code block with lang-argument"
end
```
some other text follows here.
i want some ``` backticks here.
```
def print
puts "this is a code block without lang-argument"
end
```
}