正则表达式:如果某个字符在引号内,则不匹配它
Posted
技术标签:
【中文标题】正则表达式:如果某个字符在引号内,则不匹配它【英文标题】:RegEx: Don't match a certain character if it's inside quotes 【发布时间】:2014-04-05 12:58:35 【问题描述】:披露:我已在 SO 上多次阅读 this answer,并且我知道最好不要使用正则表达式来解析 html。这个问题只是为了拓宽我对正则表达式的了解。
假设我有这个字符串:
some text <tag link="fo>o"> other text
我想匹配整个标签,但如果我使用<[^>]+>
,它只会匹配<tag link="fo>
。
如何确保引号内的>
可以被忽略。
我可以简单地编写一个带有 while 循环的解析器来执行此操作,但我想知道如何使用正则表达式。
【问题讨论】:
【参考方案1】:如果您希望它与转义双引号一起使用,请尝试:
/>(?=((?:[^"\\]|\\.)*"([^"\\]|\\.)*")*([^"\\]|\\.)*$)/g
例如:
const gtExp = />(?=((?:[^"\\]|\\.)*"([^"\\]|\\.)*")*([^"\\]|\\.)*$)/g;
const nextGtMatch = () => ((exec) =>
return exec ? exec.index : -1;
)(gtExp.exec(xml));
如果您要解析一堆 XML,您需要设置 .lastIndex
。
gtExp.lastIndex = xmlIndex;
const attrEndIndex = nextGtMatch(); // the end of the tag's attributes
【讨论】:
【参考方案2】:(<.+?>[^<]+>)|(<.+?>)
您可以创建两个正则表达式,而不是使用“|”将它们放在一起, 在这种情况下:
(<.+?>[^<]+>) #will match some text <tag link="fo>o"> other text
(<.+?>) #will match some text <tag link="foo"> other text
如果第一个大小写匹配,它不会使用第二个正则表达式,所以请确保将特殊情况放在首位。
【讨论】:
【参考方案3】:正则表达式:
<[^>]*?(?:(?:('|")[^'"]*?\1)[^>]*?)*>
在线演示:
http://regex101.com/r/yX5xS8
完整解释:
我知道这个正则表达式可能会让人头疼,所以这是我的解释:
< # Open HTML tags
[^>]*? # Lazy Negated character class for closing HTML tag
(?: # Open Outside Non-Capture group
(?: # Open Inside Non-Capture group
('|") # Capture group for quotes, backreference group 1
[^'"]*? # Lazy Negated character class for quotes
\1 # Backreference 1
) # Close Inside Non-Capture group
[^>]*? # Lazy Negated character class for closing HTML tag
)* # Close Outside Non-Capture group
> # Close HTML tags
【讨论】:
你确定[^\1]
做了你认为的事情吗?我不认为\1
可以在这样的字符类中使用。
你是对的!我真傻。我对其进行了更改,使其成为引号的否定字符类,因为无论如何这都是我们将与第 1 组匹配的全部。虽然当我们开始在双引号中包含单引号时这会带来问题......我确实有一个解决方案,但它很长。
惊人的华丽和美丽的正则表达式!谢谢!
为什么不用正则表达式?一个用于"
分隔参数,一个用于'
?然后仅在第二个不匹配时尝试第二个正则表达式?
或者,就此而言,您可以使用(?:'[^']*'|"[^"]*")
(而不是(?:('|")[^'"]*?\1)
)。 (你真的不需要引号内的*?
限定符。无论你使用*
还是*?
,这里的匹配总是相同的。)【参考方案4】:
这是对 Vasili Syrakis 答案的轻微改进。它完全分别处理"…"
和'…'
,并且不使用*?
限定符。
正则表达式
<[^'">]*(("[^"]*"|'[^']*')[^'">]*)*>
演示
http://regex101.com/r/jO1oQ1
说明
< # start of HTML tag
[^'">]* # any non-single, non-double quote or greater than
( # outer group
( # inner group
"[^"]*" # "..."
| # or
'[^']*' # '...'
) #
[^'">]* # any non-single, non-double quote or greater than
)* # zero or more of outer group
> # end of HTML tag
此版本略比 Vasilis 的版本更好,因为"…"
中允许使用单引号,'…'
中允许使用双引号,并且像 <a href='>
这样的(不正确的)标签将不匹配。
这比 Vasili 的解决方案略差,因为组被捕获了。如果您不希望这样,请在所有位置将(
替换为(?:
。 (仅使用(
会使正则表达式更短,并且更具可读性)。
【讨论】:
以上是关于正则表达式:如果某个字符在引号内,则不匹配它的主要内容,如果未能解决你的问题,请参考以下文章
正则表达式 (C#):匹配 > < 或(非法 XML 字符)但仅当包含在引号内时