这是我曾经尝试过的最艰难的事情之一.多年来我一直在搜索,但我找不到这样做的方法 - 匹配一个不被给定字符包围的字符串,如引号或更大/小于符号.
像这样的正则表达式可以匹配不在HTML链接中的URL,不在引号中的SQL table.column值以及许多其他内容.
Example with quotes:
Match [THIS] and "something with [NOT THIS] followed by" or even [THIS].
Example with <,>, & "
Match [URL] and <a href="[NOT URL]">or [NOT URL]</a>
Example with single quotes:
WHERE [THIS] LIKE '%[NOT THIS]'
Run Code Online (Sandbox Code Playgroud)
基本上,如果字符串(THIS)没有被给定的char包围,你如何匹配?
\b(?:[^"'])([^"']+)(?:[^"'])\b
Run Code Online (Sandbox Code Playgroud)
这是一个测试模式:像我想的那样的正则表达式只匹配第一个"引用".
引用,"引用我,以免我引用你!"
Ala*_*ore 14
最佳解决方案取决于您对输入的了解.例如,如果您正在寻找未用双引号括起来的内容,那是否意味着双引号将始终正确平衡?他们可以用反斜杠逃脱,还是用单引号括起来?
假设最简单的情况 - 没有嵌套,没有转义 - 你可以使用这样的前瞻:
preg_match('/THIS(?=(?:(?:[^"]*+"){2})*+[^"]*+\z)/')
Run Code Online (Sandbox Code Playgroud)
找到目标(THIS)后,前瞻基本上会计算该点之后的双引号,直到字符串结束.如果它们有奇数,则匹配必须在一对双引号内发生,因此它无效(前瞻失败).
正如您所发现的,这个问题不太适合正则表达式; 这就是为什么所有提出的解决方案都依赖于真实正则表达式中没有的功能,例如捕获组,外观,不情愿和占有量词.如果没有占有量词或原子团,我甚至都不会尝试这个.
编辑:为了扩大该方案考虑到可以用反斜杠转义双引号,你只需要更换正则表达式匹配"任何东西,这不是一个双引号"的部分:
[^"]
Run Code Online (Sandbox Code Playgroud)
"任何不是引用或反斜杠,或反斜杠后跟任何东西":
(?:[^"\\]|\\.)
Run Code Online (Sandbox Code Playgroud)
由于反斜杠转义序列相对较少,因此当您处于正则表达式的那一部分时,尽可能匹配尽可能多的非转义字符是值得的:
(?:[^"\\]++|\\.)
Run Code Online (Sandbox Code Playgroud)
总而言之,正则表达式变为:
'/THIS\d+(?=(?:(?:(?:[^"\\]++|\\.)*+"){2})*+(?:[^"\\]++|\\.)*+$)/'
Run Code Online (Sandbox Code Playgroud)
应用于您的测试字符串:
'Match THIS1 and "NOT THIS2" but THIS3 and "NOT "THIS4" or NOT THIS5" ' +
'but \"THIS6\" is good and \\\\"NOT THIS7\\\\".'
Run Code Online (Sandbox Code Playgroud)
...它应该匹配'THIS1','THIS3','THIS4'和'THIS6'.