質問

このコードは動作します:

from pyparsing import *

zipRE = "\d{5}(?:[-\s]\d{4})?" 
fooRE = "^\!\s+.*"

zipcode = Regex( zipRE )
foo = Regex( fooRE )

query = ( zipcode | foo )



tests = [ "80517", "C6H5OH", "90001-3234", "! sfs" ]

for t in tests:
    try:
        results = query.parseString( t )
        print t,"->", results
    except ParseException, pe:
        print pe

私は2つの問題にこだわってます:

1 - トークンを解析するカスタム関数を使用する方法。例えば、私は数が郵便番号であるかどうかを判断する代わりに、正規表現のいくつかのカスタムロジックを使用したい場合。 代わりに:

zipcode = Regex( zipRE )

おそらくます:

zipcode = MyFunc()

2 - どのように私は、文字列がTO解析するかを決定します。 「80001」「郵便番号」に解析しますが、どのように私は、この使用してpyparsingを決定するのですか?私は、その内容の文字列を解析していないよしかし、単にそれがクエリの種類を決定します。

役に立ちましたか?

解決

あなたの2番目の質問は簡単ですので、私はそれが最初にお答えします。別の表現に結果名を割り当てるために、クエリを変更します:

query = ( zipcode("zip") | foo("foo") ) 

これで、返された結果でのgetName()を呼び出すことができます:

print t,"->", results, results.getName()

寄付ます:

80517 -> ['80517'] zip
Expected Re:('\\d{5}(?:[-\\s]\\d{4})?') (at char 0), (line:1, col:1)
90001-3234 -> ['90001-3234'] zip
! sfs -> ['! sfs'] foo

あなたが別の関数を呼び出すために、結果のfoonessやzipnessを使用しようとしている場合は、あなたのfooと郵便番号式に解析アクションを取り付けることにより、解析時にこれを行うことができます:

# enclose zipcodes in '*'s, foos in '#'s
zipcode.setParseAction(lambda t: '*' + t[0] + '*')
foo.setParseAction(lambda t: '#' + t[0] + '#')

query = ( zipcode("zip") | foo("foo") ) 

今与えます:

80517 -> ['*80517*'] zip
Expected Re:('\\d{5}(?:[-\\s]\\d{4})?') (at char 0), (line:1, col:1)
90001-3234 -> ['*90001-3234*'] zip
! sfs -> ['#! sfs#'] foo

は、あなたの最初の質問については、私は正確にあなたが何を意味するか、関数の種類を知りません。 Pyparsingは、(ワード、キーワード、リテラル、CaselessLiteralとして)だけで正規表現よりも多くの解析クラスを提供し、あなたは「+」、それらを組み合わせることで、あなたのパーサを構成する「|」、「^」、「〜」「@」と'*' 演算子。たとえば、あなたが米国の社会保障番号を解析したかったが、正規表現を使用しない場合は、使用することができます:

ssn = Combine(Word(nums,exact=3) + '-' + 
        Word(nums,exact=2) + '-' + Word(nums,exact=4))

Wordが単一のトークンにマッチしたトークンを連結組み合わせて、そのコンストラクタで指定した文字で構成された連続的な「言葉」のために一致します。

あなたが「/」sので区切られ、このような数字の潜在的なリストのために解析したい場合は、使用します:

delimitedList(ssn, '/')

または全くdelimtersと、1と3の間、そのような数字があった場合、使用

ssn * (1,3)

そして任意の式は、結果の名前を持っているか、それらに添付の行動を解析し、さらに解析中に解析された結果、または機能性を豊かにすることができます。あなたも、フォワードクラスを使用してなど、括弧のネストしたリスト、算術式、として再帰的なパーサを構築することができます。

私はpyparsingを書いた私の意図は、基本的なビルディングブロックからパーサのこの組成物は、パーサーを作成するための主要な形になることでした。人々は自分のパーサを構築することができなかった場合、彼らは間違いなく、時間をかけてその力を証明している正規表現の形式、に戻って落ちる可能性 - それだけで私は究極のエスケープバルブ(私も何であったか)として正規表現を追加した後のリリースにありました。

あるいは、一つの他のポスターが示唆するように、あなたはpyparsingソースを開き、既存のクラスのサブクラス1、またはあなた自身を書き、その構造、次のことができます。ここでペア文字にマッチするクラスがあります:

class PairOf(Token):
    """Token for matching words composed of a pair
       of characters in a given set.
    """
    def __init__( self, chars ):
        super(PairOf,self).__init__()
        self.pair_chars = set(chars)

    def parseImpl( self, instring, loc, doActions=True ):
        if (loc < len(instring)-1 and 
           instring[loc] in self.pair_chars and
           instring[loc+1] == instring[loc]):
            return loc+2, instring[loc:loc+2]
        else:
            raise ParseException(instring, loc, "Not at a pair of characters")

だからます:

punc = r"~!@#$%^&*_-+=|\?/"
parser = OneOrMore(Word(alphas) | PairOf(punc))
print parser.parseString("Does ** this match @@@@ %% the parser?")

与えるます:

['Does', '**', 'this', 'match', '@@', '@@', '%%', 'the', 'parser']

(の漏れに注意末尾単一 '?')

他のヒント

あなたはどの1つの文字列の一致を知っているように、

あなたは、別途郵便番号やFOOを使用することができます。

zipresults = zipcode.parseString( t )
fooresults = foo.parseString( t )

私はpyparsingモジュールを持っていないが、クラスではなく、機能Regexにする必要があります。

代わりにあなたのサブクラスを使用し、その後、動作をカスタマイズするために必要に応じて

あなたにできることはそれからサブクラスとオーバーライドメソッドです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top