我需要在正则表达式中使用逻辑AND。
类似于
jack AND james
匹配以下字符串
'hi jack 这里是 james'
'hi james 这里是 jack'
它接着解释了正向前瞻用于断言后面的内容与某个表达式匹配,而不会占用该匹配表达式中的字符。前瞻和后顾,统称为“环视”,是零长度断言... 环视实际上匹配字符, 但然后放弃匹配,仅返回结果:匹配或不匹配。这就是它们被称为“断言”的原因。 它们不会消耗字符串中的字符,而只是断言是否可能存在匹配。
jack
和james
的表达式:^(?=.*\bjack\b)(?=.*\bjames\b).*$
括号内以 ?=
开头的表达式是正向前瞻。下面我将分解该模式:
^
表示被匹配的字符串的开始位置。(?=.*\bjack\b)
是第一个正向前瞻,表示接下来的内容必须与 .*\bjack\b
匹配。.*
表示任意字符出现零次或多次。\b
表示任意单词边界(空格、开头、结尾等)。jack
就是这四个字符连写(下一个正向前瞻中的 james
同理)。$
表示被匹配的字符串的结束位置。所以,第一个正向前瞻表示“后面紧跟(并且不是前后瞻)的表达式必须以零个或多个任意字符、单词边界和 jack
,再以单词边界结尾”,第二个正向前瞻表示“后面紧跟的表达式必须以零个或多个任意字符、单词边界和 james
,再以单词边界结尾”。两个正向前瞻后是 .*
,它只是零次或多次匹配任意字符,然后是 $
,它匹配字符串结束位置。
因此,“从任意字符开始,然后是 jack 或 james,最后以任意字符结尾”满足第一个正向前瞻,因为有一些字符紧随其后,然后是单词 jack
,它也满足第二个正向前瞻,因为有一些字符(其中恰好包括 jack
,但这并不是满足第二个正向前瞻的必要条件)紧随其后,然后是单词 james
。两个正向前瞻都没有断言字符串结束位置,所以接下来的 .*
可以匹配超出两个前瞻匹配范围的内容,例如“最后以任何字符结尾”。
我想你明白了,但为了更加清楚,以下是反转了 jack
和 james
的情况,即“从任意字符开始,然后是 james 或 jack,最后以任意字符结尾”;它满足第一个正向前瞻,因为有一些字符紧随其后,然后是单词 james
,它也满足第二个正向前瞻,因为有一些字符(其中恰好包括 james
,但这并不是满足第二个正向前瞻的必要条件)紧随其后,然后是单词 jack
。与前面相同,两个正向前瞻都没有断言字符串结束位置,所以接下来的 .*
可以匹配超出两个前瞻匹配范围的内容,例如“最后以任何字符结尾”。
这种方法的优点是可以轻松指定多个条件。
^(?=.*\bjack\b)(?=.*\bjames\b)(?=.*\bjason\b)(?=.*\bjules\b).*$
vim
语法:^\(.*\<jack\>\)\@=\(.*\<james\>\@=\).*$
或者 \v^(.*<jack>)@=(.*<james>)@=.*$
这是一个用于在 vim
编辑器中匹配文本的正则表达式。它的含义是匹配包含“jack”但不包含“james”的任何行。其中,\(
和 \)
用于分组,\@=
表示只有当组内的内容存在时才匹配该组,\<
和 \>
表示单词的开头和结尾,\v
则表示使用“非规范模式”,使得正则表达式更加简洁。 - mykhal\b
在这里是什么意思? - user2286243尝试:
james.*jack
如果你想同时拥有两者,那么使用or
运算符:james.*jack|jack.*james
james.*?jack|jack.*?james
。这对于大文本有所帮助。 - Jekis.
表示任何字符或数字可以出现在它的位置。
*
表示前一个字符或数字可以出现零次或多次。
|
表示“或”。
因此,
james.*jack
要搜索 james
,然后是任意数量的字符,直到出现jack
。
因为你要么想要jack.*james
,要么想要james.*jack
因此命令:
jack.*james|james.*jack
简短而精炼
(?=.*jack)(?=.*james)
[
"xxx james xxx jack xxx",
"jack xxx james ",
"jack xxx jam ",
" jam and jack",
"jack",
"james",
]
.forEach(s => console.log(/(?=.*james)(?=.*jack)/.test(s)) )
element (?=.*jack)
的结果将是 element
,而对于 (?=.*jack)
将没有结果。也在此处尝试了示例字符串:https://regex101.com。 - sygneto您可以做:
\bjack\b.*\bjames\b|\bjames\b.*\bjack\b
jack
和一个 james
的匹配。jack
和一个 james
jack
和一个 james
,不允许有两个 jack
或两个 james
,我们可以设计类似于以下的表达式:^(?!.*\bjack\b.*\bjack\b)(?!.*\bjames\b.*\bjames\b)(?=.*\bjames\b)(?=.*\bjack\b).*$
(?!.*\bjack\b.*\bjack\b)
and,
(?!.*\bjames\b.*\bjames\b)
我们还可以简化为:
^(?!.*\bjack\b.*\bjack\b|.*\bjames\b.*\bjames\b)(?=.*\bjames\b|.*\bjack\b).*$
如果您想简化/更新/探索表达式,可以在regex101.com的右上角面板上找到详细说明。您可以观看匹配步骤或在此调试器链接中修改它们,如果您感兴趣的话。该调试器演示了正则表达式引擎如何逐步消耗一些示例输入字符串并执行匹配过程。
jex.im将正则表达式可视化:
const regex = /^(?!.*\bjack\b.*\bjack\b|.*\bjames\b.*\bjames\b)(?=.*\bjames\b|.*\bjack\b).*$/gm;
const str = `hi jack here is james
hi james here is jack
hi james jack here is jack james
hi jack james here is james jack
hi jack jack here is jack james
hi james james here is james jack
hi jack jack jack here is james
`;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}
jack
和一个james
这个表达式也可以设计成先使用一个james
再使用一个jack
,类似于下面的表达式:
^(?!.*\bjack\b.*\bjack\b|.*\bjames\b.*\bjames\b)(?=.*\bjames\b.*\bjack\b).*$
反之亦然:
^(?!.*\bjack\b.*\bjack\b|.*\bjames\b.*\bjames\b)(?=.*\bjack\b.*\bjames\b).*$
\b
之后我们需要加上.*
吗?还是没有也可以工作? - RavinderSingh13.*
确实是没有用的,只有在需要完全匹配时才需要它。 - bobble bubble由于不是所有时候都支持 lookaround
,因此您可以利用正则表达式的量词功能。
(\bjames\b){1,}.*(\bjack\b){1,}|(\bjack\b){1,}.*(\bjames\b){1,}
\b(word1|word2|word3|word4|etc)\b
我在这里测试过了:https://rubular.com/r/Pgn2d6dXXXHoh7 - captain_majidhi jack here is james
hi james here is jack
(?=.*jack)(?=.*james)
不会突出显示任何内容。您可以通过在大多数Unix shell中运行此命令进行测试:printf 'hi jack here is james\nhi james here is jack\n' | grep --color --perl '(?=.*jack)(?=.*james)'
.*
。这样会突出显示一些东西 - 整行 - 但如果我们的目标是突出显示我们正在寻找的单词以及这些单词之间的内容,那就没有帮助了。
Vim分支技术(也称为\&
)会突出显示一些看起来可能有用的内容,但这可能不是你想要的。对于相同的输入文本,Vim搜索/.*james\&.*jack
会突出显示hi jack
和hi james here is jack
。要从shell中测试,请运行以下命令:printf 'hi jack here is james\nhi james here is jack\n' | vim -R - '+/.*james\&.*jack'
这里的杰克是詹姆斯
和这里的詹姆斯是杰克
。要从命令行测试此功能:printf 'hi jack here is james\nhi james here is jack\n' | grep --color --perl 'james.*jack|jack.*james'