正则表达式匹配每个字符至少一次

正则表达式匹配每个字符至少一次

问题描述:

我正在写一个解决谜题的应用程序。我正在搜索一些字符组合的文本,如果我有一组字符[abcd],那么我需要在文本中查找仅包含字符abcd的子字符串,并且还必须包含至少一个字符 - 以便字符abcd匹配dcba或abbcdd,但不匹配acd,bbcd或abced。如果使用正则表达式[abcd] +,那么我将得到不包含每个字符的子字符串正则表达式匹配每个字符至少一次

+6

您需要添加蟒蛇标签。你还需要展示你已经尝试过的东西,并解释什么不起作用。这不是GIMME DA CODE网站。 – tchrist 2012-03-18 19:07:48

+0

你可以给我们更多的细节?这太模糊了。 – 2012-03-18 19:24:37

为什么要在这里使用正则表达式?

def hasChars(search_string, chars): 
    return all(x in search_string for x in chars) 

>>> hasChars('aaabcd', 'abc') 
True 

如果字符串必须至少包含abcd的,但可以包含其他人,那么这将工作

(?=.*a)(?=.*b)(?=.*c)(?=.*d)

如果,以及它们只能包含abcd的,那么这可能是更好的

^(?=.*a)(?=.*b)(?=.*c)(?=.*d)[abcd]+$

更新

要回答你的问题,如果你正在寻找一个浮动的版本,这个你想要做什么:

(?=([abcd]{4,}))(?=[bcd]*a)(?=[acd]*b)(?=[abd]*c)(?=[abc]*d)\1

扩展:

 # At POSition 
(?=    # Lookahead 
    (     # Capture grp 1 
     [abcd]{4,}   # Get 4 or more (greedy) 'a' or 'b' or 'c' or 'd' characters 
    ) 
) 
(?=    # Lookahead, check for 'a' (still at POS) 
    [bcd]*a    # 0 or more [bcd]'s then 'a' 
) 
(?=    # Lookahead, check for 'b' (still at POS) 
    [acd]*b    # 0 or more [acd]'s then 'b' 
) 
(?=    # Lookahead, check for 'c' (still at POS) 
    [abd]*c    # 0 or more [abd]'s then 'c' 
) 
(?=    # Lookahead, check for 'd' (still at POS) 
    [abc]*d    # 0 or more [abc]'s then 'd' 
) 
\1     # Backref to capt grp 1, consume it 

    # Passed test, now at POSition + length of capture group 1 

你可能能够从搜索字符串中系统地构造正则表达式。我不太了解python,所以这里是一个如何在Perl中完成的示例。但请注意,字符串越长,查找匹配所需的时间就越长,但这应该相当快。

use strict; 
use warnings; 

my $samp = 'bddaaabcabbad characters abcd matches dcba or abbcdd, but not acd, bbcd or abced'; 

my $regex = '(?=([abcd]{4,}))(?=[bcd]*a)(?=[acd]*b)(?=[abd]*c)(?=[abc]*d)\1'; 

while ($samp =~/$regex/xg) 
{ 
    print "Found '$1'\n"; 
} 

# Regex construction 
# ------------------------------ 
my @AryofSearchStrs = (
'abcd', 
'%^&*', 
'hi()there', 
'==-yes', 
); 

for my $search_string (@AryofSearchStrs) 
{ 
    my $str = $search_string; 
    while($str =~ s/(.)(.*)\1/$1$2/g) {} 

    my @astr = split '', $str; 

    my $rxformed = '(?=([' . quotemeta($str) . ']{' . length($str) . ',}))'; 
    for (my $i = 0; $i < @astr; $i++) 
    { 
     $rxformed .= 
     '(?=[' 
     . join('', map { quotemeta($_) } @astr[0..($i-1), ($i+1)..$#astr]) 
     . ']*' 
     . quotemeta($astr[$i]) 
     . ')'; 
    } 
    $rxformed .= '\1'; 

    print "\n\n============\n"; 
    print "Search string = '$search_string'\n"; 
    print "Normalized = '$str'\n"; 
    print "Formed regex = \n$rxformed\n"; 
} 

输出

Found 'bddaaabcabbad' 
Found 'abcd' 
Found 'dcba' 
Found 'abbcdd' 


============ 
Search string = 'abcd' 
Normalized = 'abcd' 
Formed regex = 
(?=([abcd]{4,}))(?=[bcd]*a)(?=[acd]*b)(?=[abd]*c)(?=[abc]*d)\1 


============ 
Search string = '%^&*' 
Normalized = '%^&*' 
Formed regex = 
(?=([\%\^\&\*]{4,}))(?=[\^\&\*]*\%)(?=[\%\&\*]*\^)(?=[\%\^\*]*\&)(?=[\%\^\&]*\*)\1 


============ 
Search string = 'hi()there' 
Normalized = 'hi()ter' 
Formed regex = 
(?=([hi\(\ \)ter]{8,}))(?=[i\(\ \)ter]*h)(?=[h\(\ \)ter]*i)(?=[hi\ \)ter]*\()(?=[hi\(\)ter]*\)(?=[hi\(\ ter]*\))(?=[hi\(\ \)er]*t)(?=[hi\(\ \)tr]*e)(?=[hi\(\ \)te]*r)\1 


============ 
Search string = '==-yes' 
Normalized = '=-yes' 
Formed regex = 
(?=([\=\-yes]{5,}))(?=[\-yes]*\=)(?=[\=yes]*\-)(?=[\=\-es]*y)(?=[\=\-ys]*e)(?=[\=\-ye]*s)\1 
+0

谢谢!后一种方法的作用是匹配整个字符串,但是我实际上需要在更大的文本内找到字符序列作为子字符串。我实际上并不确定上述方法是如何工作的,所以我无法从中解决问题。我已经通过了涵盖上述语法元素的正则表达式教程,但我不明白它们在这种情况下是如何使用的。任何在正确的方向理解这一点将非常感激。 – 2012-03-19 00:27:04

+0

@python whisperer - 增加了一个正则表达式和解释来获得你需要的子串。与往常一样,如果您发现这些有用,请务必点名并接受答案(如果可以的话)。 – sln 2012-03-20 02:36:27