声明:我在此处的SO上多次阅读了这篇答案,我知道不应该使用正则表达式解析HTML。这个问题只是为了用正则表达式扩展我的知识。
假设我有这个字符串:
some text <tag link="fo>o"> other text
我想匹配整个标签,但是如果我使用<[^>]+>
,它只会匹配<tag link="fo>
。
如何确保引号内的>
可以被忽略。
我可以轻松地编写一个while循环解析器来完成这个任务,但我想知道如何使用正则表达式实现。
<[^>]*?(?:(?:('|")[^'"]*?\1)[^>]*?)*>
我知道这个正则表达式可能让人头疼,所以这里是我的解释:
< # 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
"…"
和'…'
,并且不使用*?
限定符。
<[^'">]*(("[^"]*"|'[^']*')[^'">]*)*>
< # 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
"..."
内使用,双引号可以在'...'
内使用,并且不会匹配(错误的)标签,例如<a href='>
。(
替换为(?:
。(只使用(
使正则表达式更短,也更易读)。(<.+?>[^<]+>)|(<.+?>)
你可以创建两个正则表达式,然后使用“|”将它们组合在一起,例如:
(<.+?>[^<]+>) #will match some text <tag link="fo>o"> other text
(<.+?>) #will match some text <tag link="foo"> other text
/>(?=((?:[^"\\]|\\.)*"([^"\\]|\\.)*")*([^"\\]|\\.)*$)/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
[^\1]
做了你想做的事情吗?我认为\1
不能在字符类中使用。 - zrajm(?:'[^']*'|"[^"]*")
(而不是(?:('|")[^'"]*?\1)
)。在引号内部,你真的不需要使用*?
限定符。无论你使用*
还是*?
,这里的匹配结果总是相同的。 - zrajm