意外的Ruby Regexp行为

时间:2018-05-11 13:23:52

标签: ruby regex string

给定以下字符串str

\begin{align*}
\intertext{Here is some text}
x^{2}+2x+3=2\\
\intertext{Here is some more}
\end{align*}

我想将对齐字符串移到对齐环境之外,如下所示:

Here is some text
\begin{align*}
x^{2}+2x+3=2\\
\end{align*}
Here is some more

请注意,我只想在\ begin {something}或\ end {something}之前或之后出现intertext时才这样做。考虑到这一点,我写了以下Regexps:

begin_align = /\\begin\{([^}]*)\}\n\\intertext\{([^}]*)\}/m
end_align = /\\intertext\{([^}]*)\}\n\\end\{([^}]*)\}/m

由于括号中的分组元素,当我调用m = str.match(begin_align)时,我可以抓取m[0](匹配的字符串),m[1](应该是给定的环境,{{1在这个例子中)和align*,它应该是intertext中的文本。如果我写m[2],我会str.match(m[0])。为什么?

我找到了解决方法:如果我改为呼叫nil,我会得到一个匹配。 然而,如果我尝试将此匹配替换为str.match(Regexp.quote(m[0])),则说没有任何反应。如果我写str.sub(Regexp.quote(m[0]),''),我会得到预期的结果。怎么会?

在我尝试调试此示例时,我注意到了其他一些我无法理解的内容。如果我写 str.sub(m[0],'')
尽管它们是相同的字符串,但我得不到匹配。如果我逃脱'第二个"\\begin{align".match("\\begin{align")为:
\\
然后我得到一个匹配。如果我然后尝试把星号
"\\begin{align".match("\\\\begin{align")
我得到"\\begin{align*".match("\\\\begin{align*"):它忽略了星号。我必须用#<MatchData "\\begin{align">来逃避第二个星号。发生了什么事?

1 个答案:

答案 0 :(得分:0)

m[0]

\\begin{align*}\n\\intertext{Here is some text}

Note on .sub()

  

模式通常为Regexp;如果作为String给出,任何   它包含的正则表达式元字符将被解释   字面上。

因此m[0]包含*,这是一个量词。从'*'.sub(),它只代表文字*字符。但是将.match()视为'*',它被解释为量词,以及str.match('*')抛出错误的原因。正则表达式上下文中的align*表示在任意数量的alig个字符之前的字符串n

因此要使.match()工作,你必须关心这些特殊字符,但对于.sub(),使用Regexp.quote并将其作为字符串传递只是一团糟。