【问题标题】:How do I fix this multiline regular expression in Ruby?如何在 Ruby 中修复这个多行正则表达式?
【发布时间】:2011-08-08 19:51:48
【问题描述】:

我在 Ruby 中有一个正则表达式在多行模式下无法正常工作。

我正在尝试将 Markdown 文本转换为 Redmine 中使用的 Textile-eque 标记。问题出在我用于转换代码块的正则表达式中。它应该找到任何以 4 个空格或制表符开头的行,然后将它们包装在 pre 标记中。

markdownText = '# header

some text that precedes code

    var foo = 9;
    var fn = function() {}

    fn();

some post text'

puts markdownText.gsub!(/(^(?:\s{4}|\t).*?$)+/m,"<pre>\n\\1\n</pre>")

预期结果:

# header

some text that precedes code

<pre>
    var foo = 9;
    var fn = function() {}

    fn();
</pre>

some post text

问题是结束 pre 标记打印在文档的末尾,而不是在“fn();”之后。我尝试了以下表达式的一些变体,但不匹配:

gsub!(/(^(?:\s{4}|\t).*?$)+^(\S)/m, "<pre>\n\\1\n</pre>\\2")

如何让正则表达式只匹配缩进的代码块?你可以在 Rubular here 上测试这个正则表达式。

【问题讨论】:

  • 为什么不在你的正则表达式中包含换行符:((?:\s{4}|\t).*?\n)+
  • @Mladen Jablanovic 我无法让您的示例使用此代码:puts markdownText.gsub!(/((?:\s{4}|\t).*?\n)+/,"&lt;pre&gt;\n\\1\n&lt;/pre&gt;")\n$ 的行为有何不同?
  • 这只是获取缩进部分的正则表达式(在 Rubular 中尝试过),而不是一个完整的工作 gsub-ready 解决方案(因此,只是一个评论)。

标签: ruby regex multiline


【解决方案1】:

首先,注意Ruby中的'm'多行模式等价于其他语言的's'单行模式。换一种说法; Ruby 中的'm' 模式表示:“点匹配所有”

这个正则表达式可以很好地匹配类似降价的代码部分:

re = / # Match a MARKDOWN CODE section.
    (\r?\n)              # $1: CODE must be preceded by blank line
    (                    # $2: CODE contents
      (?:                # Group for multiple lines of code.
        (?:\r?\n)+       # Each line preceded by a newline,
        (?:[ ]{4}|\t).*  # and begins with four spaces or tab.
      )+                 # One or more CODE lines
      \r?\n              # CODE folowed by blank line.
    )                    # End $2: CODE contents
    (?=\r?\n)            # CODE folowed by blank line.
    /x
result = subject.gsub(re, '\1<pre>\2</pre>')

这需要在代码段之前和之后有一个空行,并允许在代码段本身内有空行。它允许\r\n\n 行终止。请注意,这不会去除每行之前的前 4 个空格(或制表符)。这样做将需要更多的代码复杂性。 (我不是红宝石人,所以对此无能为力。)

我建议查看降价源本身,看看它是如何完成的。

【讨论】:

  • 感谢详细的 cmets ridgerunner。我认为你的答案是迄今为止唯一真正符合我的规格的开箱即用的答案。
【解决方案2】:

Here 是另一种捕获单个块中所有缩进行的方法

((?:^(?: {4}|\t)[^\n]*$\n?)+)

【讨论】:

    【解决方案3】:

    您的示例输入对我有用。

    markdownText.gsub(/\n?((\s{4}.+)+)/, "\n<pre>#{$1}\n</pre>")
    

    【讨论】:

      【解决方案4】:

      /^(\s{4}|\t)+.+\;\n$/m

      工作得更好一些,但仍会选择我们不想要的换行符。 here 是rubular。

      【讨论】:

      • 在我发布这个之后看到了 ridgerunner 的帖子,绝对是一个更好的答案。
      猜你喜欢
      • 2020-05-03
      • 2022-12-21
      • 1970-01-01
      • 2021-09-01
      • 1970-01-01
      • 2020-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多