2011-11-14 14 views
3

私は正規表現の初心者ですが、正規表現クエリ内の任意の文字を順番に照合する方法を理解しています(例:[abc]はa、b、私は "abc"がabcと正確に一致すると信じています)。すべての文字を正規表現で任意の順序で一致させる

しかし、すべての文字abcと任意の順序で一致する正規表現クエリを作成するにはどうすればよいですか?たとえば、「cab」または「bracket」と一致させる必要があります。私はスクリプト言語としてPythonを使用しています(このことが重要かどうかはわかりません)。 Pythonで

答えて

10

、私は、この目的のためにregualar表現を使用することはありませんが、むしろセット:

>>> chars = set("abc") 
>>> chars.issubset("bracket") 
True 
>>> chars.issubset("fish") 
False 
>>> chars.issubset("bad") 
False 

正規表現有用であるが、さまざまなツールがより適切である状況があります。あなたの文字列がabcの少なくとも一つの発生を含んでいる場合

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

試合:

+0

感謝を答え。私が正規表現を使いたい理由は、文字列に対して複数の種類のマッチを実行しようとしているからです。マッチエンド。開始と終了の両方に一致します。部分文字列と完全に一致します。私はそれらのクエリの正規表現を使用していますが、私はあなたの応答から "任意の順序ですべての文字を一致させる"正規表現ではないので、私はそのクエリを分離する必要があります何かではないと思います。 – steve8918

+0

エレガントでコンパクトです。なぜ私はまだJavaを使用しているのだろうかと思う: –

8

この先読みアサーションで行うことができます。

ご覧のとおり、これは正規表現がうまくいくものではありません。

は、私が行っているでしょう:

if all(char in mystr for char in "abc"): 
    # do something 

はスピードのチェック:

>>> timeit.timeit(stmt='chars.issubset("bracket");chars.issubset("notinhere")', 
... setup='chars=set("abc")') 
1.3560583674019995 
>>> timeit.timeit(stmt='all(char in "bracket" for char in s);all(char in "notinhere" for char in s)', 
... setup='s="abc"') 
1.4581878714681409 
>>> timeit.timeit(stmt='r.match("bracket"); r.match("notinhere")', 
... setup='import re; r=re.compile("(?=.*a)(?=.*b)(?=.*c)")') 
1.0582279123082117 

はねえ、見て、正規表現の勝利を!これは、さらに長い検索文字列のためにも当てはまる:ここ

>>> timeit.timeit(stmt='chars.issubset("bracketed");chars.issubset("notinhere")', 
... setup='chars=set("abcde")') 
1.4316702294817105 
>>> timeit.timeit(stmt='all(char in "bracketed" for char in s);all(char in "notinhere" for char in s)', 
... setup='s="abcde"') 
1.6696223364866682 
>>> timeit.timeit(stmt='r.match("bracketed"); r.match("notinhere")', 
... setup='import re; r=re.compile("(?=.*a)(?=.*b)(?=.*c)(?=.*d)(?:.*e)")') 
1.1809254199004044 
+0

...しかし、Svenのソリューションはおそらくより効率的です。 –

+1

どちらが効率的かわかりませんが、どちらもかなり読みやすいようです。とにかく、私の答えの主な目的は、正規表現を使用せずに "正規表現"バッジを取得する私の秘密の探求のいくつかの進歩をすることです。 :) –

+0

@SvenMarnach:それは価値があり、高貴な目標です。私はそれ以外の方法で行ってきました:) –

2

regexソリューション対issubsetのはtimeit比較です。小さな文字列の

import re 

def using_lookahead(text): 
    pat=re.compile(r'^(?=.*a)(?=.*b)(?=.*c)') 
    return pat.search(text) 

def using_set(text): 
    chars=set('abc') 
    return chars.issubset(text) 

issubsetはわずかに速くなることがあります。長い文字列の場合

% python -mtimeit -s'import test' "test.using_set('bracket')" 
100000 loops, best of 3: 2.63 usec per loop 
% python -mtimeit -s'import test' "test.using_lookahead('bracket')" 
100000 loops, best of 3: 2.87 usec per loop 

、正規表現は明らかに速いです:

  • 試合は後半に来るとき:

    % python -mtimeit -s'import test' "test.using_set('o'*1000+'bracket')" 
    10000 loops, best of 3: 49.7 usec per loop 
    % python -mtimeit -s'import test' "test.using_lookahead('o'*1000+'bracket')" 
    100000 loops, best of 3: 6.66 usec per loop 
    
  • 試合が早く来る:

    % python -mtimeit -s'import test' "test.using_set('bracket'+'o'*1000)" 
    10000 loops, best of 3: 50 usec per loop 
    % python -mtimeit -s'import test' "test.using_lookahead('bracket'+'o'*1000)" 
    100000 loops, best of 3: 13.9 usec per loop 
    

(コメントでの質問に答えるために:) r'^(?=.*a)(?=.*b)(?=.*c)'は試合を知らせるために使用することができますため

In [40]: pat=re.compile(r'^(?=.*a)(?=.*b)(?=.*c)') 

In [41]: pat.search('bracket') 
Out[41]: <_sre.SRE_Match object at 0x9f9a6b0> 
+0

これは、一致するものに空の文字列を返します。とにかく、すべての文字が入力に含まれていると主張する場合は、それは問題ありません。しかし、もし一致したテキストを取得したいのであれば、それは役に立たないでしょう。 –

+0

一致するテキストは文字列全体です。正規表現がそれを返す必要はありません。とにかく、 'issubset'はboolだけを返すので、それを偶数比較にするために、正規表現は何もしてはいけません。 – unutbu

関連する問題