次のような 2 つの引用符の間に情報を含む文字列がいくつかあります。
cc "1/11/2A" "1/20+21/1 1" "XX" 0
引用符間の部分を一致させるために使用re.findall('\"*\"', line)
していますが、何らかの理由で機能しません。私は他にも多くのことを試しましたが、何も入っていない空のリストしか得られません。私は何を間違っていますか?
0 個以上の引用符とそれに続く引用符が一致しています。代わりに負の文字クラスを使用します。
re.findall(r'"[^"]*"', line)
負の文字クラスの周りにキャプチャ グループを配置することができます。
re.findall(r'"([^"]*)"', line)
.findall()
引用符自体を含めずに、引用符内のすべてを返すようになりました。
>>> import re
>>> re.findall(r'"([^"]*)"', 'cc "1/11/2A" "1/20+21/1 1" "XX" 0')
['1/11/2A', '1/20+21/1 1', 'XX']
負の文字クラス表記とは、ここで指定された文字セットに含まれていない[^...]
任意の文字に一致することを意味します。したがって、引用符ではないすべての文字に一致し、一致する文字を引用符内のすべてのものにきちんと制限します。[^"]
*
ファイル名のワイルドカードのように、「何でも」一致することを期待していたようです。
しかし、それは正規表現で意味するものではありません。前の式を変更して、その式の 0 個以上のコピーに一致させます。
ファイル名スタイルのワイルドカードを取得するには、.*
.
.
ただし、 .を含むすべてのものに一致するため、実際には機能しません"
。"
したがって、式の残りの部分だけを残して、最後の文字まですべてを取得します。つまりfindall
、3 つの小さな文字列ではなく、1 つの大きな文字列が検出されます。
を使用して、繰り返しを非貪欲にすることで修正できます.*?
。これにより、最初 の まですべてが一致します"
。
そう:
>>> re.findall('\".*?\"', line)
['"1/11/2A"', '"1/20+21/1 1"', '"XX"']
Martijn Pieters の答えは、おそらく概念的により明確だと思います。私がこれを提供したのは、これがあなたが問題を攻撃しようとしていた方法かもしれないと思うからであり、どのようにしてそこにたどり着くことができたのかを示したかった.
補足として、生の文字列を使用すると正規表現コードが読みやすくなるため、余分なバックスラッシュ エスケープを取り除くことができます。この場合、バックスラッシュはすでに不要です。単一引用符で囲まれた文字列または正規表現で二重引用符をエスケープする必要はありません。しかし、正規表現パーサーに到達できるように、Python パーサーによってエスケープする必要があるものとそうでないものを覚えようとする代わりに、生の文字列を使用する方が簡単です。そう:
>>> re.findall(r'".*?"', line)
['"1/11/2A"', '"1/20+21/1 1"', '"XX"']
である必要がありますr'"[^"]*"'
。パターン"
は、連続する 1 つ以上の文字と一致します。
In [4]: re.findall(r'"[^"]*"', line)
Out[4]: ['"1/11/2A"', '"1/20+21/1 1"', '"XX"']