我正在尝试将以下行解析为3个变量
BS<syntax interpolate='#'> #greeting</syntax>AS
我需要捕获:$1 = BS
、$2 = interpolate='#'
和$3 = AS
。
问题是我的正则表达式$2
是'interpolate='#'>#greeting</syntax'
。显然它在第二个>
上匹配,但我的任何尝试都无法说服它在第一个上匹配。字符<
、>
和syntax
都被称为%syntax
散列中的变量,我的正则表达式是
$line =~ /(\w+)$syntax{'start'}\Q$syntax{'syntax'}\E\s+(.+?)\Q$syntax{'end'}\E(\w+)/i
我试过用([^\Q$syntax{'end'}\E]+)
作为第二个括号,甚至是([^\>]+)
,在这些情况下,它甚至不匹配。奇怪的是,(.+)
和(.+?)
之间似乎没有任何区别。有人能解决这个问题吗?
3条答案
按热度按时间2lpgd9681#
为了使
.+?
在所示字符串中的第一个>
处停止,模式.+?>\w+
中的\w+
需要匹配#greeting</syntax>AS
--其中有许多字符\w
不匹配(空格、#
、<
、/
)。一种解决方法是列出所有这些,
[\s#<\/\w]+
(而不是\w+
)。另一种方法是使用更宽松的模式而不是\w
。我不知道什么更适合您的问题...当
<
(等)从散列被内插时,这都成立;此处不需要\Q
-\E
。但是,如果确实需要捕获
AS
,那么我们需要多一点。或
是合适的(为了可读性,我放弃了使用
%syntax
散列)。hl0ma9xz2#
(?:(?!STRING).)*
与STRING
的关系就像[^CHAR]
与CHAR
的关系一样。我对抽象语法元素的好处表示怀疑。如果你硬编码它们,它就变成了:
注意,我避免了非贪婪修饰符是不安全的,使用它是不安全的,它并不能阻止你得到比你期望的更多的匹配。
使用正则表达式做这些是非常脆弱的。一个合适的解析器会一次又一次地为自己付出代价。而且你也不需要我们的帮助来编写复杂的正则表达式模式。
hmae6n7t3#
这里我有几样东西要推荐。
首先,让散列中的子模式决定它们需要转义什么。我看不到散列,但我怀疑您无意中转义了应该是正则表达式字符的正则表达式字符。
第二,当你插入其他模式时,不要使用编号捕获。如果它们本身有捕获,你会丢掉你的编号。相反,使用命名捕获:
下面是输出,根据需要从哈希中获取值:
但是,如果您有这些简单的XML/HTML外观片段,DOM可以挑选出您需要的部分:
以下是您需要的所有内容,但您可能需要删除一些空白: