web-dev-qa-db-ja.com

「生の文字列正規表現」とは正確に何で、どのように使用できますか?

'\'文字に関するpython regex のドキュメントから):

解決策は、正規表現パターンにPythonの生の文字列表記を使用することです。バックスラッシュは、'r'で始まる文字列リテラルでは特別な方法で処理されません。したがって、r"\n"'\''n'を含む2文字の文字列であり、"\n"は改行を含む1文字の文字列です。通常、パターンは、この生の文字列表記を使用してPythonコードで表現されます。

この生の文字列表記とは何ですか?生の文字列形式を使用する場合、それは"*"がゼロ以上のインジケーターではなくリテラル文字として解釈されることを意味しますか?それは明らかに正しいことはできません、そうでなければ正規表現はその力を完全に失います。しかし、それが生の文字列である場合、"\n"が文字通りバックスラッシュと"n"である場合、どのように改行文字を認識するのでしょうか?

従わない.

報奨金の編集:

生の文字列正規表現が改行、タブ、文字セットにどのように一致するかを理解しようとしています。生の文字列パターンがバックスラッシュを通常の文字以外のものとして認識しない場合、\wは単語に、_\dは数字またはその他すべてに使用します。良い例をいくつか使用できます。

51

Zarkonnenの回答はあなたの質問に答えますが、直接ではありません。もっと率直になり、ザルコネンから賞金を手に入れることができるかどうか見てみましょう。

「生の文字列正規表現」および「生の文字列パターン」という用語の使用をやめると、おそらくこれを理解しやすくなるでしょう。これらの用語は、Pythonソースコードの特定の文字列の表現と、その文字列が表す正規表現とは、2つの別個の概念を混同します。

実際、これらをそれぞれ独自の構文を持つ2つの異なるプログラミング言語と考えると便利です。 Python言語には、特定のコンテンツで文字列を構築し、正規表現システムを呼び出すソースコードがあります。正規表現システムには、文字列オブジェクトに存在し、文字列に一致するソースコードがあります。両方の言語は、エスケープ文字としてバックスラッシュを使用します。

まず、文字列は一連の文字(つまり、バイトまたはUnicodeコードポイント。ここでは区別はそれほど重要ではない)であることを理解します。 Pythonソースコード。raw文字列は、単にこれらの表現の1つです。2つの表現が結果として生じる場合、同じ文字シーケンスで、同等の動作を生成します。

backslash文字の後にn文字が続く2文字の文字列を想像してください。 backslashの文字値が92で、nの文字値が110であることがわかっている場合、この式は文字列を生成します。

_s = chr(92)+chr(110)
print len(s), s

2 \n
_

従来のPython文字列表記_"\n"_はこの文字列を生成しません。代わりに、改行文字を含む1文字の文字列を生成します。 Python docs2.4.1。文字列リテラル たとえば、「バックスラッシュ(\)文字は、改行、バックスラッシュ自体、引用文字など、特別な意味を持つ文字をエスケープするために使用されます。」

_s = "\n"
print len(s), s

1 
 
_

(この例では改行は表示されませんが、注意深く見ると、「1」の後に空白行が表示されます。)

2文字の文字列を取得するには、別のbackslash文字を使用して、元のbackslash文字の特別な意味をエスケープする必要があります。

_s = "\\n"
print len(s), s

2 \n
_

多くのバックスラッシュ文字を含む文字列を表現したい場合はどうでしょうか? Python docs2.4.1。文字列リテラル continue、「文字列リテラルにはオプションで文字「r」または「R」を接頭辞として付けることができます。そのような文字列はraw文字列と呼ばれ、バックスラッシュエスケープシーケンスの解釈に異なるルールを使用します。」以下は、生の文字列表現を使用した2文字の文字列です。

_s = r"\n"
print len(s), s

2 \n
_

したがって、3つの異なる文字列表現があり、すべて同じ文字列または文字シーケンスを提供します。

_print chr(92)+chr(110) == "\\n" == r"\n"
True
_

それでは、正規表現を見てみましょう。 Pythonドキュメント、7.2。reRegular expression operations は、「正規表現ではバックスラッシュ文字( '\')を使用して特殊な形式を示すか、特殊な意味を呼び出さずに特殊文字を使用できるようにします。これは、Pythonが文字列リテラルで同じ目的に同じ文字を使用することと衝突します...」

改行文字に一致するPython正規表現オブジェクトが必要な場合は、backslash)文字で構成される2文字の文字列が必要ですn文字により、次のコード行はすべて、progを改行文字を認識する正規表現オブジェクトに設定します。

_prog = re.compile(chr(92)+chr(110))
prog = re.compile("\\n")
prog = re.compile(r"\n")
_

なぜ 「通常、パターンはPythonこの生の文字列表記を使用したコード」で表現されます。 ?正規表現は静的文字列であることが多く、便利に表現されるためです。使用可能なさまざまな文字列リテラル表記から、正規表現にbackslash文字が含まれる場合、生の文字列が便利な選択です。

質問

[〜#〜] q [〜#〜]:式re.compile(r"\s\tWord")?はどうですか? [〜#〜] a [〜#〜]:正規表現のコンパイルから文字列を分離し、それらを個別に理解することで理解しやすくなります。

_s = r"\s\tWord"
prog = re.compile(s)
_

文字列sには8文字が含まれています:backslash、ans、aバックスラッシュ、at、そして4文字Word

[〜#〜] q [〜#〜]:タブとスペース文字はどうなりますか? [〜#〜] a [〜#〜]:Python言語レベル、文字列sにはtabおよびspace文字はありません。4文字で始まります:backslashsbackslasht。正規表現一方、systemは、その文字列を正規表現言語のソースコードとして扱います。つまり、「空白文字、タブ文字、および4文字Wordで構成される文字列に一致する」という意味です。

[〜#〜] q [〜#〜]:それがバックラッシュ-sとバックスラッシュ-tとして扱われている場合、どのようにマッチしますか? [〜#〜] a [〜#〜]:「you」および「that」という単語をより具体的にすると、質問がより明確になる可能性があります。正規表現システムは、どのように式backlash-sおよびbackslash-tと一致しますか? 「任意の空白文字」および「tab文字」として。

[〜#〜] q [〜#〜]:または、3文字の文字列backslash-n-newlineがある場合はどうなりますか? [〜#〜] a [〜#〜]:Python言語では、3文字の文字列バックスラッシュ-n-newlineは、従来の文字列_"\\n\n"_、またはrawと従来の文字列_r"\n" "\n"_、またはその他の方法で表すことができます。任意の2つの連続したnewline文字。

N.B.すべての例とドキュメントのリファレンスは、Python 2.7。

Update:@Vladislav Zorovと@ m.buettnerの回答、および@Aerovistaeのフォローアップの質問からの説明を組み込みました。

71
Jim DeLaHunt

これらの質問のほとんどには多くの単語が含まれており、特定の質問に対する答えを見つけるのは難しいかもしれません。

通常の文字列を使用し、「\ t」などのパターンをRegExパーサーに渡すと、Pythonはそのリテラルをタブバイト(0x09)を含むバッファーに変換します。

生の文字列を使用し、r "\ t"のようなパターンをRegExパーサーに渡すと、Pythonは解釈を行わず、2バイトのバッファーを作成します。 「\」および「t」(0x5c、0x74)。

RegExパーサーは、シーケンス '\ t'の処理方法を認識しています。これはタブと一致します。また、0x09文字をどう処理するかも知っています。これはタブにも一致します。ほとんどの場合、結果は区別できません。

したがって、何が起こっているのかを理解するための鍵は、ここで使用されている2つのパーサーがあることを認識することです。 1つ目はPythonパーサーであり、文字列リテラル(または生の文字列リテラル)をバイトシーケンスに変換します。2つ目はPythonの正規表現パーサーであり、コンパイルされた正規表現へのバイト。

14
Geoff Gerrietts

通常の文字列を使用して\を含む正規表現を記述する場合の問題は、\\ごとに\を記述する必要があることです。したがって、文字列リテラル"stuff\\things"r"stuff\things"は同じ文字列を生成します。これは、バックスラッシュと一致する正規表現を作成する場合に特に役立ちます。

通常の文字列を使用すると、文字列\に一致する正規表現は"\\\\"になります!

どうして? \を2回エスケープする必要があるためです。1回は正規表現構文、もう1回は文字列構文です。

次のように、三重引用符を使用して改行を含めることができます。

r'''stuff\
things'''

通常、pythonは\- newlineを行の継続として処理しますが、これは生の文字列には当てはまりません。また、バックスラッシュは生の文字列の引用符をエスケープしますしたがって、生の文字列リテラルr"\""は、文字列\"を生成しますこれは、生の文字列リテラルをバックスラッシュで終了できないことを意味します。

詳細については、 Python documentation の字句解析セクションを参照してください。

5
Zarkonnen

RegExはPythonの一部ではなく、独自のパーサーとコンパイラを備えた別のプログラミング言語であるという考えに苦労しているようです。生文字列は、RegExの「ソースコード」をRegExパーサーに安全に取得し、\d\w\nなどの文字シーケンスに意味を割り当てます。

この問題は、PythonおよびRegExpsが\をエスケープ文字として使用しているためです。これは偶然の一致です。他のエスケープ文字(改行ですが、RegExpsで「\ n」を使用する必要があります。これらの言語では、生の文字列と非生の文字列を区別する必要がないという利点があります。どちらもテキストを変換しようとしません異なるエスケープシーケンスに反応するためです。

4
Vladislav Zorov

関連するPythonマニュアルセクション( "String and Bytes literals"))には、生の文字列リテラルの明確な説明があります。

文字列リテラルとバイトリテラルの両方には、オプションで文字「r」または「R」をプレフィックスとして付けることができます。このような文字列は生の文字列と呼ばれ、バックスラッシュをリテラル文字として扱います。その結果、文字列リテラルでは、生の文字列の '\ U'および '\ u'エスケープは特別に扱われません。 Python 2.xの生のUnicodeリテラルは、Python 3.xの 'ur'構文はサポートされていません。

バージョン3.3の新機能:生バイトリテラルの「rb」プレフィックスが「br」の同義語として追加されました。

バージョン3.3の新機能:デュアルPython 2.xおよび3.xコードベースのメンテナンスを簡素化するために、Unicodeレガシーリテラル(u'value ')のサポートが再導入されました。詳細については、PEP 414を参照してください。 。

三重引用符で囲まれた文字列では、エスケープされていない改行と引用符が許可されます(そして保持されます)。 (「引用符」は、文字列を開くために使用される文字、つまり 'または "。)

接頭辞「r」または「R」が存在しない限り、文字列内のエスケープシーケンスは、標準Cで使用される規則と同様の規則に従って解釈されます。認識されるエスケープシーケンスは次のとおりです。

エスケープシーケンスの意味

\ newlineバックスラッシュと改行は無視されます
\バックスラッシュ()
\'一重引用符(')
\"二重引用符(")
\a ASCII Bell(BEL)
\b ASCII Backspace(BS)
\f ASCII Formfeed(FF)
\n ASCII改行(LF)
\r ASCIIキャリッジリターン(CR)
\t ASCII水平タブ(TAB)\ v ASCII垂直タブ(VT)
\ooo 8進数値ooo(1,3)を持つ文字
\xhh 16進値hh(2,3)の文字

文字列リテラルでのみ認識されるエスケープシーケンスは次のとおりです。

エスケープシーケンス意味注\ N {name} Unicodeデータベースの名前付き文字(4)\ uxxxx 16ビット16進値xxxx(5)の文字\ Uxxxxxxxx 32ビット16進値xxxxxxxxの文字(6)

ノート:

  1. 標準Cと同様に、最大3桁の8進数が受け入れられます。

  2. 標準Cとは異なり、正確に2桁の16進数が必要です。

  3. バイトリテラルでは、16進および8進のエスケープは、指定された値のバイトを示します。文字列リテラルでは、これらのエスケープは指定された値を持つUnicode文字を示します。

  4. バージョン3.3で変更:名前エイリアス[1]のサポートが追加されました。

  5. サロゲートペアの一部を形成する個々のコードユニットは、このエスケープシーケンスを使用してエンコードできます。正確に4桁の16進数が必要です。

  6. この方法でUnicode文字をエンコードできますが、Pythonが16ビットコード単位(デフォルト)を使用するようにコンパイルされている場合、基本多言語面(BMP)以外の文字はサロゲートペアを使用してエンコードされます。 。正確に8桁の16進数が必要です。

標準Cとは異なり、認識されないエスケープシーケンスはすべて文字列にそのまま残ります。つまり、バックスラッシュは文字列に残ります。 (この動作は、デバッグ時に役立ちます。エスケープシーケンスの入力ミスがあった場合、結果の出力は壊れていると簡単に認識されます。)文字列リテラルでのみ認識されるエスケープシーケンスは、バイトの認識されないエスケープのカテゴリに分類されることに注意することも重要ですリテラル。

生の文字列であっても、文字列の引用符はバックスラッシュでエスケープできますが、バックスラッシュは文字列に残ります。たとえば、r "\" "はバックスラッシュと二重引用符の2つの文字で構成される有効な文字列リテラルです。r"\"は有効な文字列リテラルではありません(生の文字列でも奇数個のバックスラッシュで終わることはできません)。具体的には、生の文字列は単一のバックスラッシュで終わることはできません(バックスラッシュは次の引用文字をエスケープするためです)。また、単一のバックスラッシュとそれに続く改行は、行の継続としてではなく、文字列の一部としてこれらの2文字として解釈されることに注意してください。

1
Lorenzo Gatti