5

引数のリストのような入力があります。

input1 = '''
title="My First Blog" author='John Doe'
'''

値は一重引用符または二重引用符で囲むことができますが、エスケープすることもできます。

input2 = '''
title='John\'s First Blog' author="John Doe"
'''

正規表現を使用して、一重引用符または二重引用符とエスケープされた引用符のいずれかを説明するキーと値のペアを抽出する方法はありますか?

Pythonを使用すると、次の正規表現を使用して、エスケープされていない引用符を処理できます。

rex = r"(\w+)\=(?P<quote>['\"])(.*?)(?P=quote)"

その場合の返品は次のとおりです。

import re
re.findall(rex, input1)
[('title', '"', 'My First Blog'), ('author', "'", 'John Doe')]

import re
re.findall(rex, input2)
[('title', "'", 'John'), ('author', '"', 'John Doe')]

後者は正しくありません。エスケープされた引用符を処理する方法がわかりません-おそらく(。*?)セクションにあります。私はPython正規表現に投稿された回答のソリューションを使用して、一重引用符で囲まれたテキストと一致させ、エスケープされた引用符(およびタブ/改行)を無視して無駄にしました。

技術的には、引用符を返すためにfindallは必要ありません。キーと値のペアだけでなく、簡単に処理できます。

どんな助けでもいただければ幸いです!ありがとう!

4

2 に答える 2

5

編集

私の最初の正規表現ソリューションにはバグがありました。そのバグはあなたの入力文字列のエラーを隠しました:input2あなたが思っているものではありません:

>>> input2 = '''
... title='John\'s First Blog' author="John Doe"
... '''
>>> input2      # See - the apostrophe is not correctly escaped!
'\ntitle=\'John\'s First Blog\' author="John Doe"\n'  

input2生の文字列を作成する (または二重のバックスラッシュを使用する)必要があります。

>>> input2 = r'''
... title='John\'s First Blog' author="John Doe"
... '''
>>> input2
'\ntitle=\'John\\\'s First Blog\' author="John Doe"\n'

エスケープされた引用符を正しく処理する正規表現を使用できるようになりました。

>>> rex = re.compile(
    r"""(\w+)# Match an identifier (group 1)
    =        # Match =
    (['"])   # Match an opening quote (group 2)
    (        # Match and capture into group 3:
     (?:     # the following regex:
      \\.    # Either an escaped character
     |       # or
      (?!\2) # (as long as we're not right at the matching quote)
      .      # any other character.
     )*      # Repeat as needed
    )        # End of capturing group
    \2       # Match the corresponding closing quote.""", 
    re.DOTALL | re.VERBOSE)
>>> rex.findall(input2)
[('title', "'", "John\\'s First Blog"), ('author', '"', 'John Doe')]
于 2012-11-05T20:57:54.377 に答える
5

ティムの後方参照の使用は式を過度に複雑にし、(ここで推測すると) 処理を遅くしていると思います。標準的なアプローチ (フクロウの本で使用) は、単一引用符と二重引用符で囲まれた文字列を別々に照合することです。

rx = r'''(?x)
    (\w+) = (
        ' (?: \\. | [^'] )* '
        |
        " (?: \\. | [^"] )* "
        |
        [^'"\s]+
    )
'''

少し後処理を追加すれば問題ありません。

input2 = r'''
title='John\'s First Blog' author="John Doe"
'''

data = {k:v.strip("\"\'").decode('string-escape') for k, v in re.findall(rx, input2)}
print data
# {'author': 'John Doe', 'title': "John's First Blog"}

おまけとして、これは のような引用符で囲まれていない属性にも一致しますweight=150

追加: 正規表現を使用しないよりクリーンな方法は次のとおりです。

input2 = r'''
title='John\'s First Blog' author="John Doe"
'''

import shlex

lex = shlex.shlex(input2, posix=True)
lex.escapedquotes = '\"\''
lex.whitespace = ' \n\t='
for token in lex:
    print token

# title
# John's First Blog
# author
# John Doe
于 2012-11-05T22:06:52.443 に答える