Ruby Regex或Parser

时间:2012-08-18 15:31:09

标签: ruby regex parsing

我有一个我想要解析的字符串,看起来有点像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会在我的情况下起作用,但我不介意被证明是错误的。

1 个答案:

答案 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
```
}