ruby - 意外的 Ruby 正则表达式行为
问题描述
给定以下字符串,str
:
\begin{align*}
\intertext{Here is some text}
x^{2}+2x+3=2\\
\intertext{Here is some more}
\end{align*}
我想将 intertext 字符串移到 align 环境之外,如下所示:
Here is some text
\begin{align*}
x^{2}+2x+3=2\\
\end{align*}
Here is some more
请注意,我只想在互文出现在 \begin{something} 或 \end{something} 之前或之后立即执行此操作。考虑到这一点,我编写了以下正则表达式:
begin_align = /\\begin\{([^}]*)\}\n\\intertext\{([^}]*)\}/m
end_align = /\\intertext\{([^}]*)\}\n\\end\{([^}]*)\}/m
由于括号中的分组元素,当我调用 时m = str.match(begin_align)
,我可以抓取m[0]
(匹配的字符串)、m[1]
(在本例中应该是给定的环境align*
)和m[2]
,它应该是 intertext 中的文本。如果我写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">
:它忽略了星号。我必须用 . 转义第二个星号\\*
。这是怎么回事?
解决方案
m[0]
:
\\begin{align*}\n\\intertext{Here is some text}
注意事项 .sub()
:
模式通常是
Regexp
; 如果作为 a 给出String
,它包含的任何正则表达式元字符都将按字面意思解释。
所以m[0]
contains *
which 是一个量词。就它而言'*'
,.sub()
它只是一个字面*
字符。但由于.match()
它'*'
被解释为量词和str.match('*')
抛出错误的原因。align*
在正则表达式上下文中,表示alig
前面任意数量的n
字符的字符串。
因此,.match()
为了工作,您必须关心这些特殊字符,但使用并将其作为字符串传递.sub()
只是一团糟。Regexp.quote
推荐阅读
- swiftui - 视图不会在嵌套 ForEach 循环中重新呈现
- regex - 如果条件,bash中的奇怪正则表达式行为
- reactjs - 将动态道具传递给延迟加载组件?
- dynamics-crm - 是否可以在本地版本 (8.1) 中将 svg 文件上传到 Dynamics CRM webresource
- java - 当mysql为键'UK_pttkmqgejqcvdojl6gdkt8wi0'错误提供重复条目'10:78:5b:9f:0e:c1'时如何查找重复记录
- xamarin.android - 如何从 SearchView xamarin android 获取输入文本?
- java - 为嵌套的 jar 文件创建 fileinputstream,即 jar inside jar
- import - javac编译的非必要导入
- php - Actions-On-Google/Dialogflow:在 agentId 的平台响应中找不到 RichResponse 或 SystemIntent
- r - 在函数中生成表达式并在 R 中返回