正则表达式:匹配除特定模式之外的所有内容
Posted
技术标签:
【中文标题】正则表达式:匹配除特定模式之外的所有内容【英文标题】:Regex: match everything but specific pattern 【发布时间】:2010-12-13 20:14:30 【问题描述】:我需要一个能够匹配所有内容的正则表达式但是一个以特定模式开头的字符串(特别是index.php
以及后面的内容,例如index.php?id=2342343
)
【问题讨论】:
你不想匹配什么特定模式? 如果字符串匹配,您是否无法匹配您的模式并且不做某事? @ThomasOwens:这取决于。这取决于表达式的哪一部分应该被否定。如果要否定整个表达式,那么您就得到了一点。例如,如果您想编写“如果字符串不包含 'Bruce' 作为子字符串,则执行某些操作”,您可以直接使用 /Bruce/,并将否定放入 if 语句中,在正则表达式之外.但可能是你想否定一些子表达式。比如说,您正在寻找类似 firstname lastname 之类的内容,其中 firstname 是 Bruce,lastname 是除 XYZ 之外的所有内容,其中 XYZ 是某个名为 Bruce 的名人的姓氏。 【参考方案1】:正则表达式:匹配所有内容但:
一个字符串以特定模式开始(例如,任何 - 也为空 - 字符串不以foo
开头):
用于 NFA 的基于前瞻的解决方案:
^(?!foo).*$
^(?!foo)
基于否定字符类的解决方案适用于不支持环视的正则表达式引擎:
^(([^f].2|.[^o].|.2[^o]).*|.0,2)$
^([^f].2|.[^o].|.2[^o])|^.0,2$
一个字符串以一个特定的模式结束(比如说,没有world.
在最后):
基于 Lookbehind 的解决方案:
(?<!world\.)$
^.*(?<!world\.)$
前瞻解决方案:
^(?!.*world\.$).*
^(?!.*world\.$)
POSIX 解决方法:
^(.*([^w].5|.[^o].4|.2[^r].3|.3[^l].2|.4[^d].|.5[^.])|.0,5)$
([^w].5|.[^o].4|.2[^r].3|.3[^l].2|.4[^d].|.5[^.]$|^.0,5)$
一个字符串包含特定文本(比如,不匹配具有foo
的字符串):
基于环视的解决方案:
^(?!.*foo)
^(?!.*foo).*$
POSIX 解决方法:
使用在线正则表达式生成器www.formauri.es/personal/pgimeno/misc/non-match-regex
一个字符串包含特定的字符(比如,避免匹配具有|
符号的字符串):
^[^|]*$
一个字符串等于某个字符串(比如说,不等于foo
):
基于环视:
^(?!foo$)
^(?!foo$).*$
POSIX:
^(.0,2|.4,|[^f]..|.[^o].|..[^o])$
字符序列:
PCRE(匹配除cat
之外的任何文本):/cat(*SKIP)(*FAIL)|[^c]*(?:c(?!at)[^c]*)*/i
或/cat(*SKIP)(*FAIL)|(?:(?!cat).)+/is
其他允许环视的引擎:(cat)|[^c]*(?:c(?!at)[^c]*)*
(或(?s)(cat)|(?:(?!cat).)*
,或(cat)|[^c]+(?:c(?!at)[^c]*)*|(?:c(?!at)[^c]*)+[^c]*
)然后用语言检查:如果组1匹配,它不是我们需要的,否则,如果不为空,则获取匹配值
某个单个字符或一组字符:
使用negated character class:[^a-z]+
(小写ASCII 字母以外的任何字符)
匹配除|
之外的任何字符:[^|]+
演示说明:换行符\n
用于演示中的否定字符类中,以避免匹配溢出到相邻行。测试单个字符串时不需要它们。
锚注:在许多语言中,使用\A
来定义字符串的明确开头,而\z
(在Python 中是\Z
,在javascript 中是$
OK) 来定义字符串的末尾。
点注:在许多风格中(但不是 POSIX、TRE、TCL),.
匹配任何字符但换行符字符。确保为 .
使用相应的 DOTALL 修饰符(PCRE/Boost/.NET/Python/Java 中的 /s
和 Ruby 中的 /m
)来匹配任何字符,包括换行符。
反斜杠说明:在必须使用允许转义序列的 C 字符串声明模式的语言中(例如 \n
换行符),您需要将反斜杠加倍以转义特殊字符,以便引擎可以将它们视为文字字符(例如,在 Java 中,world\.
将被声明为 "world\\."
,或者使用字符类:"world[.]"
)。使用原始字符串文字 (Python r'\bworld\b'
)、C# 逐字字符串文字 @"world\."
或像 /world\./
这样的斜线字符串/正则表达式文字符号。
【讨论】:
写得好!对于“一个字符串(不)等于某个字符串”的情况,以^(?!foo$)
为例,为什么美元符号必须在括号内才能使表达式起作用?我期待^(?!foo)$
给出相同的结果,但事实并非如此。
@GrantHumphries:当$
锚在前瞻内时,它是条件的一部分,是零宽度断言的一部分。如果它在外面,就像在^(?!foo)$
中一样,它将是 消费 模式的一部分,需要在字符串开始之后立即结束字符串,这使得负前瞻无关紧要,因为它总是会返回 true(字符串末尾不能有任何文本,更不用说foo
)。因此,^(?!foo$)
匹配一个字符串的开头,该字符串后面不跟 foo
,后面跟字符串结尾。 ^(?!foo)$
匹配一个空字符串。
@robots.txt 请删除这些 cmets。你在问一个 XY 问题。字符类旨在匹配单个字符,无法用它们定义字符序列。您可能应该只找到字符串开头和cot
或lan
第一次出现之间的子字符串,然后删除匹配项,例如regex.replace(myString, "^.*?(?:cot|lan)\s*", "")
。
亲爱的维克托。您已经关闭了我的问题,但是您的链接答案失败了。我已经更新了我的问题***.com/questions/60004380/…
@Dotizo Python re
库与 PCRE 完全不同。使用支持(*SKIP)(*FAIL)
动词的PyPi regex library。【参考方案2】:
我需要一个能够匹配所有内容的正则表达式,但 except 是一个 字符串 以
index.php
开头的特定模式(特别是 index.php 以及接下来的内容,例如 index.php?id=2342343)
使用方法执行
let match,
arr = [],
myRe = /([\s\S]+?)(?:index\.php\?id.+)/g;
var str = 'http://regular-viragenia/index.php?id=2342343';
while ((match = myRe.exec(str)) != null)
arr.push(match[1]);
console.log(arr);
var myRe = /([\s\S]+?)(?:index\.php\?id=.+)/g;
var str = 'http://regular-viragenia/index.php?id=2342343';
var matches_array = myRe.exec(str);
console.log(matches_array[1]);
或其他匹配
let match,
arr = [],
myRe = /index.php\?id=((?:(?!index)[\s\S])*)/g;
var str = 'http://regular-viragenia/index.php?id=2342343index.php?id=111index.php?id=222';
while ((match = myRe.exec(str)) != null)
arr.push(match[1]);
console.log(arr);
【讨论】:
【参考方案3】:您可以将^
放在字符集的开头以匹配除这些字符之外的任何字符。
[^=]*
将匹配除=
之外的所有内容
【讨论】:
没错,但它一次只处理一个字符。如果要排除两个或多个字符的序列,则必须像其他响应者所说的那样使用否定前瞻。 完美的解决方案你删除任何不受欢迎的字符但那些在模式。谢谢 @Alan, "...you have to use a negative lookahead..." 是不正确的,但我们不应该对你太苛刻,因为 Wiktor 没有发布他的答案——说明原因——直到 2016 年。【参考方案4】:不使用正则表达式如何:
// In PHP
0 !== strpos($string, 'index.php')
【讨论】:
OP 专门要求使用正则表达式...我不确定这是否有帮助! (例如,他可能在命令行上使用grep
,或 Perl/Python/任何其他语言,或在文本编辑器中使用“为每一行执行此正则表达式”命令等...)【参考方案5】:
在python中:
>>> import re
>>> p='^(?!index\.php\?[0-9]+).*$'
>>> s1='index.php?12345'
>>> re.match(p,s1)
>>> s2='index.html?12345'
>>> re.match(p,s2)
<_sre.SRE_Match object at 0xb7d65fa8>
【讨论】:
这将拒绝“index_php”或“index#php”。【参考方案6】:不是正则表达式专家,但我认为您可以从一开始就使用负前瞻,例如^(?!foo).*$
不应匹配以 foo
开头的任何内容。
【讨论】:
使用 grep 使用 -P 启用前瞻。 如果不匹配“foo”或“bar”是您想要的行为,请检查此答案:***.com/a/2404330/874824 这个答案是错误的,快速测试表明。我想你的意思是^((?!foo).)*$
(***.com/a/406408/3964381)【参考方案7】:
只需匹配/^index\.php/
,然后拒绝匹配它的任何内容。
【讨论】:
也许写成str !~ /\Aindex\.php/
。以上是关于正则表达式:匹配除特定模式之外的所有内容的主要内容,如果未能解决你的问题,请参考以下文章