Regex 正则表达式以查找正匹配和负匹配

Regex 正则表达式以查找正匹配和负匹配,regex,tcl,Regex,Tcl,我希望在regex(TCL)中匹配正负字符的组合 假设我想匹配包含'def'和不包含'hij'的行 ab def hhh -> print abdefxxhijzz -> no print hij -> no print 123defhijxyz -> no print 0def123hijxyz -> no print 我试过: {(def)(?!hij)} {(def).*(?!hij)} {.*(def).*(?!hij)} {

我希望在regex(TCL)中匹配正负字符的组合

假设我想匹配包含'def'和不包含'hij'的行

ab def hhh    -> print
abdefxxhijzz  -> no print
hij           -> no print
123defhijxyz  -> no print
0def123hijxyz -> no print
我试过:

{(def)(?!hij)}
{(def).*(?!hij)}
{.*(def).*(?!hij)}
{.*(def).*(?!hij).*}
全部错误地打印“0def123hijxyz”

在命令行中,我可以使用2个grep命令行来执行此操作

echo 0def123hijxyz | grep def | grep -v hij
你们中的一位专家能否帮助使用regexp来实现这一目标

谢谢,
Gert.

此正则表达式应适用于:

(?!.*hij)(.*def.*)

它向前查找子字符串
*hij
,如果找不到,它将匹配
(*def.*)

此正则表达式应该可以工作:

(?!.*hij)(.*def.*)

它将查找子字符串
*hij
,如果找不到,它将匹配
(.*def.*)

我将此视为两个任务,而我根本看不到需要的正则表达式

首先搜索包含所需字符串(“def”)的字符串,然后仅当该字符串通过第一次测试时,验证它不包含禁止字符串(“hij”)


根据哪一个更有可能消除最多的可能性,将此作为第一步。例如,如果更多的字符串更可能包含禁止的字符串,请首先进行该检查,因为您的代码将更高效。

我将此视为两项任务,而我根本不认为需要正则表达式

首先搜索包含所需字符串(“def”)的字符串,然后仅当该字符串通过第一次测试时,验证它不包含禁止字符串(“hij”)


根据哪一个更有可能消除最多的可能性,将此作为第一步。例如,如果更多的字符串更可能包含禁止的字符串,请首先执行该检查,因为您的代码将更高效。

您已经接近,但您需要首先执行负前瞻,并锚定它,以确保只在字符串开头应用一次

{(?n)^(?!.*hij).*def.*}
  • (?n)
    打开
    -line
    模式,允许
    ^
    在行首匹配(大多数正则表达式称之为
    多行
    模式)

  • (?!*hij)
    在整个字符串中搜索
    hij
    ,如果找到,则报告失败

  • *def.
    如果包含
    def
    ,则使用整个字符串

  • % check {^(?!.*hij.*$).*def}
    ab def hhh => 1
    abdefxxhijzz => 0
    hij => 0
    123defhijxyz => 0
    0def123hijxyz => 0
    

锚定是必要的,以防止它匹配一个字符串,其中不需要的单词位于想要的单词之前,如
hij def
。如果没有锚定,它可以通过从
i

开始查找匹配项。您已经很接近了,但是您需要首先执行负前瞻,并锚定它,以确保只在字符串开头应用一次

{(?n)^(?!.*hij).*def.*}
  • (?n)
    打开
    -line
    模式,允许
    ^
    在行首匹配(大多数正则表达式称之为
    多行
    模式)

  • (?!*hij)
    在整个字符串中搜索
    hij
    ,如果找到,则报告失败

  • *def.
    如果包含
    def
    ,则使用整个字符串

  • % check {^(?!.*hij.*$).*def}
    ab def hhh => 1
    abdefxxhijzz => 0
    hij => 0
    123defhijxyz => 0
    0def123hijxyz => 0
    

锚定是必要的,以防止它匹配一个字符串,其中不需要的单词位于想要的单词之前,如
hij def
。如果没有锚,它可以从
i

开始查找匹配项。对于这种检查,我宁愿不使用regexp,而使用字符串方法:

if {[string match *def* "0def123hijxyz"] && ![string match *hij* "0def123hijxyz"]} {
    puts "Match!"
}
字符串匹配
使用全局匹配,因此
*
是通配符

[string match*def*“0def123hijxyz”]
如果
def
在字符串中,则返回1,否则返回0


如果您仍然坚持使用regexp方法,我建议使用以下regex:

^(?!.*hij).*def
^
是行锚的开始,它使regexp仅检查一次匹配,而不是在匹配失败时重复检查匹配(即,在发现存在
hij
或没有
def
之后)

(?!.*hij)
中添加
*
可以检查整个字符串,而不是字符串中的单个位置

{(?n)^(?!.*hij).*def.*}
*def
然后尝试匹配
def
。您不必在结尾使用另一个
*
字符,除非有更多字符需要匹配,例如,
def
后跟
g
,即使中间有其他字符将是
*def..g
。最后使用这个
*
只会给regexp带来更多的工作


一些基准测试

% proc match {} {
        if {[string match *def* "0def123hijxyz"] && ![string match *hij* "0def12
3hijxyz"]} {
        }
}
% proc regmatch {} {
        if {[regexp -- {^(?!.*hij).*def} 0def123hijxyz]} {
        }
}
% puts [time match 100000]
0.49533 microseconds per iteration
% puts [time regmatch 100000]
1.38854 microseconds per iteration
% proc regmatcher {} {
        if {[regexp -- {(?n)^(?!.*hij).*def.*} 0def123hijxyz]} {
        }
}
% puts [time regmatcher 100000]
2.23913 microseconds per iteration

regexp
比简单字符串方法花费的时间长2-4倍。

对于这种检查,我宁愿不使用regexp,而使用字符串方法:

if {[string match *def* "0def123hijxyz"] && ![string match *hij* "0def123hijxyz"]} {
    puts "Match!"
}
字符串匹配
使用全局匹配,因此
*
是通配符

[string match*def*“0def123hijxyz”]
如果
def
在字符串中,则返回1,否则返回0


如果您仍然坚持使用regexp方法,我建议使用以下regex:

^(?!.*hij).*def
^
是行锚的开始,它使regexp仅检查一次匹配,而不是在匹配失败时重复检查匹配(即,在发现存在
hij
或没有
def
之后)

(?!.*hij)
中添加
*
可以检查整个字符串,而不是字符串中的单个位置

{(?n)^(?!.*hij).*def.*}
*def
然后尝试匹配
def
。您不必在结尾使用另一个
*
字符,除非有更多字符需要匹配,例如,
def
后跟
g
,即使中间有其他字符将是
*def..g
。最后使用这个
*
只会给regexp带来更多的工作


一些基准测试

% proc match {} {
        if {[string match *def* "0def123hijxyz"] && ![string match *hij* "0def12
3hijxyz"]} {
        }
}
% proc regmatch {} {
        if {[regexp -- {^(?!.*hij).*def} 0def123hijxyz]} {
        }
}
% puts [time match 100000]
0.49533 microseconds per iteration
% puts [time regmatch 100000]
1.38854 microseconds per iteration
% proc regmatcher {} {
        if {[regexp -- {(?n)^(?!.*hij).*def.*} 0def123hijxyz]} {
        }
}
% puts [time regmatcher 100000]
2.23913 microseconds per iteration

regexp
比简单字符串方法花费的时间长2-4倍。

在测试这类东西时,制作一个小测试程序有助于:

proc check {re} {
    foreach s {"ab def hhh" "abdefxxhijzz" "hij" "123defhijxyz" "0def123hijxyz"} {
        puts "$s => [regexp $re $s]"
    }
}
让我们看看……