3

以下の正規表現をpyparsingで使用するにはどうすればよいですか? 正規表現が与えられたトークンのリストを返す必要があります。

どんな助けでも大歓迎です!ありがとうございました!

シェルでの python 正規表現の例:

>>> re.split("(\w+)(lab)(\d+)", "abclab1", 3)
>>> ['', 'abc', 'lab', '1', '']

私は pyparsing でこれを試しましたが、最初の一致が貪欲であるため、正しく取得する方法を理解できないようです。つまり、最初のトークンは'abclab'2 つのトークンの代わり'abc''lab'.

pyparsing の例 (高レベル、つまり非動作コード):

name = 'abclab1'
location = Word(alphas).setResultsName('location')
lab = CaselessLiteral('lab').setResultsName('environment')
identifier = Word(nums).setResultsName('identifier')
expr = location + lab + identifier
match, start, end = expr.scanString(name).next()
print match.asDict()
4

2 に答える 2

7

Pyparsing のクラスはほぼ左から右へと進み、FollowedBy (正の先読み) や NotAny または '~' 演算子 (負の先読み) などの明示的な式を使用して先読みが実装されます。これにより、繰り返される項目に通常一致するターミネータを検出できます。たとえば、OneOrMore(Word(alphas)) + Literal('end')「start blah blah end」のような文字列では一致が見つかりません。これは、終了の「end」が OneOrMore の繰り返し式に飲み込まれてしまうためです。修正は、繰り返される式に否定先読みを追加することです。OneOrMore(~Literal('end') + Word(alphas)) + Literal('end')つまり、アルファで構成された別の単語を読み取る前に、まずそれが「end」という単語ではないことを確認してください。

これは、繰り返しが Word などの pyparsing クラス内にある場合に失敗します。Word(alphas)単語を止める空白がない限り、アルファベット文字を読み続けます。Combine(OneOrMore(~Literal('lab') + Word(alphas, exact=1)))複雑な結合式を使用して単純なトークンを構成すると、パーサーが遅くなるため、非常に高価なものを使用してこの繰り返しに割り込む必要があります。

pyparsing Regex オブジェクトにラップされた正規表現を使用することで妥協できる場合があります。

>>> labword = Regex(r'(\w+)(lab)(\d+)')
>>> print labword.parseString("abclab1").dump()
['abclab1']

これにより、正しい種類のグループ化と検出が行われますが、グループ自体は公開されません。これを行うには、各グループに名前を追加します。pyparsing はこれらを結果名のように扱い、setResultsName を呼び出した場合と同様に、個々のフィールドにアクセスできるようにします。

>>> labword = Regex(r'(?P<locn>\w+)(?P<env>lab)(?P<identifier>\d+)')
>>> print labword.parseString("abclab1").dump()
['abclab1']
- env: lab
- identifier: 1
- locn: abc
>>> print labword.parseString("abclab1").asDict()
{'identifier': '1', 'locn': 'abc', 'env': 'lab'}

私が考えることができる他の唯一の非正規表現のアプローチは、文字列全体を読み取る式を定義してから、解析アクションで部分を分割することです。

于 2012-06-20T12:53:04.900 に答える
0

サブグループ記号 (括弧) を取り除くと、正しい答えが得られます:)

>>> re.split("\w+lab\d+", "abclab1")
['', '']
于 2012-06-20T09:30:04.387 に答える