`マッチ= re.matchの代替()。 ... `イディオム:一致した場合?
質問
あなたは何かが正規表現にマッチするかどうかを確認したい場合は、そうならば、最初のグループを印刷し、あなたのやる..
import re
match = re.match("(\d+)g", "123g")
if match is not None:
print match.group(1)
これは完全に知識をひけらかすであるが、中間match
変数がビット迷惑である..
はPerlなどの言語が一致グループのための新しい$1
..$9
変数を作成することによってこれを行う、などの..
if($blah ~= /(\d+)g/){
print $1
}
このredditのコメントでから、
with re_context.match('^blah', s) as match:
if match:
...
else:
...
..私は面白いアイデアだと思ったが、私はそれの簡単な実装を書いてます:
#!/usr/bin/env python2.6
import re
class SRE_Match_Wrapper:
def __init__(self, match):
self.match = match
def __exit__(self, type, value, tb):
pass
def __enter__(self):
return self.match
def __getattr__(self, name):
if name == "__exit__":
return self.__exit__
elif name == "__enter__":
return self.__name__
else:
return getattr(self.match, name)
def rematch(pattern, inp):
matcher = re.compile(pattern)
x = SRE_Match_Wrapper(matcher.match(inp))
return x
return match
if __name__ == '__main__':
# Example:
with rematch("(\d+)g", "123g") as m:
if m:
print(m.group(1))
with rematch("(\d+)g", "123") as m:
if m:
print(m.group(1))
(この機能は、理論的_sre.SRE_Match
オブジェクトにパッチを適用することができる)
with
ステートメントのコードブロックの実行をスキップすることができれば、それはいいだろうと..
with rematch("(\d+)g", "123") as m:
print(m.group(1)) # only executed if the match occurred
..しかし、これは私が PEP 343 から推測することができるもののベース不可能ですA>
任意のアイデア?私が言ったように、これはほとんどのコード・ゴルフであることのポイントに、本当に些細な迷惑です..
解決
Python 3.8
を開始し、代入式(PEP 572)(:=
演算子)それが条件の本体内にre.match(r'(\d+)g', '123g')
してから再使用していない場合、我々は今、両方チェックするために、変数match
における条件値None
をキャプチャすることができます:
>>> if match := re.match(r'(\d+)g', '123g'):
... print(match.group(1))
...
123
>>> if match := re.match(r'(\d+)g', 'dddf'):
... print(match.group(1))
...
>>>
他のヒント
私はそれは些細だとは思いません。私は、多くの場合、そのようなコードを書いている場合は、私のコードの周りに冗長な条件を振りかけるする必要がありますする必要はありません。
これは少し奇妙ですが、イテレータでこれを行うことができます:
import re
def rematch(pattern, inp):
matcher = re.compile(pattern)
matches = matcher.match(inp)
if matches:
yield matches
if __name__ == '__main__':
for m in rematch("(\d+)g", "123g"):
print(m.group(1))
奇妙なことは、それが反復されていない何かのためのイテレータを使用してあるということです - 。それは、条件に近くだし、一見、それぞれの試合のために複数の結果を得るために起こっているように見えるかもしれません。
これは、コンテキストマネージャは、その管理機能が完全にスキップさせることができないことを奇妙に思えるん。それが明示的に「と」の使用例ではないのですが、それは自然な拡張のように思えます。
もう一つの素敵な構文はこのようなものになるだろう
header = re.compile('(.*?) = (.*?)$')
footer = re.compile('(.*?): (.*?)$')
if header.match(line) as m:
key, value = m.group(1,2)
elif footer.match(line) as m
key, value = m.group(1,2)
else:
key, value = None, None
私はグレン・メイナードのソリューションに基づいて、これを行うための別の方法があります:
for match in [m for m in [re.match(pattern,key)] if m]:
print "It matched: %s" % match
グレンのソリューションと同様に、これは、0(なし一致する場合)又は1(一致する場合)倍itterates。
いいえサブ必要はなく、結果としてあまり整頓。
、ここで代替の答えです。
import re
class Matcher(object):
def __init__(self):
self.matches = None
def set(self, matches):
self.matches = matches
def __getattr__(self, name):
return getattr(self.matches, name)
class re2(object):
def __init__(self, expr):
self.re = re.compile(expr)
def match(self, matcher, s):
matches = self.re.match(s)
matcher.set(matches)
return matches
pattern = re2("(\d+)g")
m = Matcher()
if pattern.match(m, "123g"):
print(m.group(1))
if not pattern.match(m, "x123g"):
print "no match"
あなたは、全体の機能のための単一の再利用可能なのMatcherオブジェクトを作成し、再同じスレッドセーフで一回正規表現をコンパイルすることができ、その後、あなたは非常に簡潔にそれを使用することができます。これはまた、あなたが明白な方法でそれを逆にすることができます利点がある - 。イテレータで、あなたはその結果を反転させるために、それを伝えるためにフラグを渡す必要があるだろうということを行うには、
あなたが唯一しかし、機能ごとに単一の試合をやっている場合は、これは多くの助けではありません。あなたはそれより広い文脈でのMatcherオブジェクトを保持しません。それはBlixtのソリューションと同じ問題を引き起こすと思います。
私はwith
を使用すると、この場合の解決策ではないと思います。あなたは(ユーザーによって指定された)BLOCK
部の例外を発生し、例外を「飲み込む」に__exit__
メソッドの戻りTrue
を持っている必要があるだろう。だから、よく見ることはない。
私はPerlの構文と似た構文のために行くことをお勧めしたいです。独自の拡張re
モジュールを作成します(私はrex
それを呼ぶことにします)と、そのモジュールの名前空間で変数を設定する必要があります:
if rex.match('(\d+)g', '123g'):
print rex._1
あなたが以下のコメントに見ることができるように、この方法は、どちらもscope-もスレッドセーフです。あなたのアプリケーションは、将来的にマルチスレッドになっていないだろうと完全に特定したとの意志で、あなたがこれを使用している範囲から呼び出される関数は、のもの同じを使用することを場合にのみ、これを使用します方法ます。
これは本当にきれいに見えるではありませんが、組み込み関数のようにそれを使用してgetattr(object, name[, default])
から利益を得ることができます:
>>> getattr(re.match("(\d+)g", "123g"), 'group', lambda n:'')(1)
'123'
>>> getattr(re.match("(\d+)g", "X23g"), 'group', lambda n:'')(1)
''
の場合、マッチプリント・グループの流れ、あなたは(AB)for
ステートメントを使用することができますこの方法を模倣するために、
>>> for group in filter(None, [getattr(re.match("(\d+)g", "123g"), 'group', None)]):
print(group(1))
123
>>> for group in filter(None, [getattr(re.match("(\d+)g", "X23g"), 'group', None)]):
print(group(1))
>>>
もちろん、あなたが汚い仕事をするために少しの関数を定義することができます:
>>> matchgroup = lambda p,s: filter(None, [getattr(re.match(p, s), 'group', None)])
>>> for group in matchgroup("(\d+)g", "123g"):
print(group(1))
123
>>> for group in matchgroup("(\d+)g", "X23g"):
print(group(1))
>>>
ない完璧なソリューションが、同じstrのためのチェーンいくつかの一致オプションにあなたを認めていません。
class MatchWrapper(object):
def __init__(self):
self._matcher = None
def wrap(self, matcher):
self._matcher = matcher
def __getattr__(self, attr):
return getattr(self._matcher, attr)
def match(pattern, s, matcher):
m = re.match(pattern, s)
if m:
matcher.wrap(m)
return True
else:
return False
matcher = MatchWrapper()
s = "123g";
if _match("(\d+)g", line, matcher):
print matcher.group(1)
elif _match("(\w+)g", line, matcher):
print matcher.group(1)
else:
print "no match"
ここに私のソリューションです:
import re
s = 'hello world'
match = []
if match.append(re.match('w\w+', s)) or any(match):
print('W:', match.pop().group(0))
elif match.append(re.match('h\w+', s)) or any(match):
print('H:', match.pop().group(0))
else:
print('No match found')
必要に応じてあなたはできるだけ多くののelif の句を使用することができます。
さらに良います:
import re
s = 'hello world'
if vars().update(match=re.match('w\w+', s)) or match:
print('W:', match.group(0))
elif vars().update(match=re.match('h\w+', s)) or match:
print('H:', match.group(0))
else:
print('No match found')
両方の APPEND と更新のリターンのなしの。だから、実際にはすべてのケースでのまたはの部分を使用して、式の結果を確認する必要があります。
残念ながら、これは限りコード、すなわちしない機能で、最上位の存在として機能します。
これは私が何をすべきかです。
def re_match_cond (match_ref, regex, text):
match = regex.match (text)
del match_ref[:]
match_ref.append (match)
return match
if __name__ == '__main__':
match_ref = []
if re_match_cond (match_ref, regex_1, text):
match = match_ref[0]
### ...
elif re_match_cond (match_ref, regex_2, text):
match = match_ref[0]
### ...
elif re_match_cond (match_ref, regex_3, text):
match = match_ref[0]
### ...
else:
### no match
### ...
私は参照渡しをエミュレートする関数にリストを渡すこと、である。