81

正規表現に関するPythonのドキュメントから、文字に関して'\'

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

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

私はフォローしません。

報奨金のために編集:

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

4

7 に答える 7

109

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

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

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

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

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

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

2 \n

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

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

1 
 

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

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

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

2 \n

多くのバックスラッシュ文字を含む文字列を表現したい場合はどうしますか? Python ドキュメント2.4.1。文字列リテラルは続けます。生の文字列表現を使用した 2 文字の文字列を次に示します。

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

2 \n

したがって、3 つの異なる文字列表現があり、すべてが同じ文字列または文字列を示します。

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

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

改行文字に一致する Python 正規表現オブジェクトが必要な場合は、バックスラッシュ文字の後にn文字が続く 2 文字の文字列が必要です。次のコード行はすべて、改行文字を認識する正規表現オブジェクトに prog を設定します。

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

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

質問

Q : 表情はre.compile(r"\s\tWord")A : 正規表現のコンパイルから文字列を分離し、別々に理解することで理解しやすくなります。

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

文字列には、バックスラッシュsバックスラッシュt、および 4 つの文字のs8 文字が含まれます。Word

Q : タブとスペース文字はどうなりますか? A : Python 言語レベルでは、文字列にタブスペースs文字はありません。バックスラッシュsバックスラッシュtの4 文字で始まります。一方、正規表現システムは、その文字列を正規表現言語のソース コードとして扱います。つまり、「空白文字、タブ文字、および 4 つの文字で構成される文字列に一致する.Word

Q : バックラッシュ s とバックスラッシュ t として扱われている場合、それらをどのように一致させますか? A : 'you' と 'that' という言葉をより具体的にすると、質問がより明確になるかもしれません。「任意の空白文字」および「タブ文字」として。

Q : または、バックスラッシュ-n-改行の 3 文字の文字列がある場合はどうなりますか? A : Python 言語では、3 文字の文字列 backslash-n-newline は、従来の string "\\n\n"、または raw と従来の string r"\n" "\n"、またはその他の方法で表すことができます。正規表現システムは、2 つの連続した改行文字が見つかった場合、3 文字の文字列 backslash-n-newline と一致します。

注: すべての例とドキュメントの参照は Python 2.7 に対するものです。

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

于 2012-12-12T09:01:23.447 に答える
20

これらの質問のほとんどには多くの単語が含まれているため、特定の質問に対する答えを見つけるのが難しい場合があります.

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

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

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

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

于 2012-12-13T15:00:07.027 に答える
6

通常の文字列を使用して a を含む正規表現を記述する際の問題は\\\すべての\. したがって、文字列リテラル"stuff\\things"r"stuff\things"同じ文字列を生成します。これは、バックスラッシュに一致する正規表現を書きたい場合に特に便利です。

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

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

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

r'''stuff\
things'''

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

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

于 2012-10-13T07:49:01.590 に答える
4

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

この問題は、Python と RegExps\がエスケープ文字として使用するために発生しますが、これは偶然の一致です。他のエスケープ文字を使用する言語もあります (改行の場合は「`n」などですが、「\n」を使用する必要があります)。正規表現で)。利点は、これらの言語で生の文字列と生ではない文字列を区別する必要がないことです。これらの言語は、異なるエスケープ シーケンスに反応するため、テキストの変換と解体の両方を試みません。

于 2012-12-12T13:06:00.147 に答える
1

関連する Python マニュアル セクション (「文字列とバイト リテラル」) には、生の文字列リテラルの明確な説明があります。

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

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

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

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

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

エスケープ シーケンス 意味 注意事項

\newline バックスラッシュと改行は無視されます
\ バックスラッシュ ()
\' シングル クォート (')
\" ダブル クォート (")
\a ASCII ベル (BEL)
\b ASCII バックスペース (BS)
\f ASCII フォームフィード (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 ビット コード単位 (デフォルト) を使用するようにコンパイルされている場合、Basic Multilingual Plane (BMP) 外の文字はサロゲート ペアを使用してエンコードされます。正確に 8 桁の 16 進数が必要です。

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

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

于 2012-12-14T16:05:34.967 に答える