1

Python を使用して文字列を解析し、(コロン) で区切られた 2 つのトークンを抽出する必要があり:ます。これは、単一引用符、二重引用符で囲まれている場合もあれば、引用符なしで囲まれている場合もあります。

サンプルケースの動作:

# <input string> -> <tuple that should return> 

1) abc:def -> (abc, def)
2) abc:"def" -> (abc, def)
3) "abc":def -> (abc, def)
4) "abc":"def" -> (abc, def)
5) "a:bc":abc -> (a:bc, abc)

動作しないサンプル ケース:

# <input string> -> <tuple that should return> 

6) abc:"a:bc" -> (abc, a:bc)
7) "abcdef" -> (abcdef,)

使用した正規表現は次のとおりです。

>>> import re
>>> rex = re.compile(r"(?P<fquote>[\'\"]?)"
                     r"(?P<user>.+)"
                     r"(?P=fquote)"
                     r"(?:\:"
                     r"(?P<squote>[\'\"]?)"
                     r"(?P<pass>.+)"
                     r"(?P=squote))")

私は 2 つの問題を抱えています。最初はサンプル ケース 6) と 7) が機能してrex.matchいません。私が言いたいのは、今すぐ返すということです。fquotesquoterex.match("'abc':'def').groups()("'", "abc", "'", "def")("abc", "def")

何か案は?

ありがとう

4

3 に答える 3

1

すべてのグループを取得する必要があるのはなぜですか? 興味のあるものだけを取り、残りは無視してください。次に例を示します。

rex = re.compile(
    r"""^(?:
      (?P<fquote>['"])
      (?P<user1>(?:(?!(?P=fquote)).)+)
      (?P=fquote)
      |
      (?P<user2>[^:"'\s]+)
    )
    (?:
      :
      (?:
        (?P<squote>['"])
        (?P<pass1>(?:(?!(?P=squote)).)+)
        (?P=squote)
        |
        (?P<pass2>[^:"'\s]+)
      )
    )?
    $""", 
    re.VERBOSE)

result = rex.sub(r"\g<user1>\g<user2> : \g<pass1>\g<pass2>", subject)

その他の注意事項:

  • 引用されたフィールドと引用されていないフィールドを別々に処理するように分割すると、作業がはるかに簡単になります。グループの各ペアの 1 つが常に空になることがわかっているので、それらを連結しても安全です。

  • (?:(?!(?P=fquote)).)+一度に 1 文字を消費しますが、その文字が最初の引用と同じではないことを確認した後でのみです。終了の引用符を超えてしまうことを心配する必要はありません.+。(本当に消極的な.+?ものを使用する必要がありましたが、これはさらに優れています。)

于 2013-03-11T20:53:51.523 に答える
1
def foo(string):
    rex = re.compile(r"(?P<fquote>[\'\"]?)"
                     r"(?P<user>.+?)"
                     r"(?:(?P=fquote))"
                     r"(?:\:"
                     r"(?P<squote>[\'\"]?)"
                     r"(?P<pass>.+)"
                     r"(?P=squote))"
                     r"|(?P<sfquote>[\'\"]?)"
                     r"(?P<suser>.+)"
                     r"(?:(?P=sfquote))")
    match = rex.match(string)
    suser_match = match.group("suser")
    return (suser_match,) if suser_match else (match.group("user"), match.group("pass"))

これでうまくいきますが、私は強くお勧めしません。この種のソリューションは理解しにくく、保守も難しいため、正規表現はできるだけ単純にする必要があります。私の意見では、例として挙げたパターンのタイプにより適した文脈自由文法が必要になる場合があります (特に"abcdef"、別のグループが必要な文字列の場合)。

2番目の問題は、シンボリックグループを中に入れてもキャプチャされることです(?:...)。そのため、それらを取得してから、一致した記号グループでタプルを作成する方が簡単だと思います。

于 2013-03-11T18:03:43.380 に答える
1

csvここでは、正規表現の代わりにモジュールを使用できます。

inputs = [
    'abc:def', 'abc:"def"', '"abc":def', '"abc":"def"', '"a:bc":abc', #working
    'abc:"a:bc"', 'abcdef' # not working

]

import csv
for idx, el in enumerate(inputs, start=1):
    print idx, tuple(next(csv.reader([el], delimiter=':')))

これにより、次のことが得られます。

1 ('abc', 'def')
2 ('abc', 'def')
3 ('abc', 'def')
4 ('abc', 'def')
5 ('a:bc', 'abc')
6 ('abc', 'a:bc')
7 ('abcdef',)
于 2013-03-11T16:18:45.310 に答える