この記事の原文は
こちら です。おそらく、過剰な理論などというものはありません。この記事の最後に、正規表現に関するより詳細な資料へのリンクをいくつか提供します。しかし、詰め込むだけでなく、途中で小さなタスクを完了することですぐに知識を定着させる機会があれば、正規表現のようなトピックを掘り下げ始めるのははるかに興味深いものになるだろうと私には思えました。
始めましょう。通常、プログラミングで正規表現 (「RegEx」または単に「正規表現」) を使用することに反対する人は、Jamie Zawinski による次の引用を引用します。
「問題に直面したとき、『分かった、正規表現を使おう』と考える人もいます。 「今、彼らには 2 つの問題があります。」 実際、正規表現を使用することが良いか悪いかはまだわかりません。そして、これ自体は問題を追加するものではなく、問題を解決するものでもありません。それは単なるツールです。そして、それをどのように使用するか (正しいか間違っているか) によって、どのような結果が得られるかが決まります。たとえば、HTML パーサーを作成するために正規表現を使用しようとすると、おそらく
苦痛を経験するでしょう。ただし、たとえば、いくつかの行からタイムスタンプを抽出したいだけの場合は、おそらく問題ありません。正規表現をより簡単にマスターできるように、正規表現をゼロからわずか 20 の短いステップでマスターできるようにするこのレッスンをまとめました。このチュートリアルでは主に正規表現の基本概念に焦点を当て、必要な場合にのみより高度なトピックについて詳しく説明します。
ステップ 1: 正規表現を使用する理由
正規表現は、指定されたパターン (パターン) を使用してテキスト内の一致を検索するために使用されます。
正規表現を使用すると、テキストから単語だけでなく、特定の条件を満たす個々のリテラル文字やメタ文字、およびそれらのシーケンスを簡単かつ簡単に抽出できます。正規表現は、
メタ 文字 (ワイルドカード文字) の使用に基づいて、テキスト内の部分文字列を検索および操作するための形式的な言語です。検索には、シンボルとメタシンボルで構成され、検索ルールを定義するサンプル文字列 (英語のパターン、ロシア語では「テンプレート」、「マスク」と呼ばれることが多い) が使用されます。テキストを操作するには、置換文字列を追加で指定します。これには特殊文字も含めることができます。 パターンは
dog
次の文の単語のように単純なものにすることができます。
素早い茶色のキツネが怠惰な犬を飛び越えます。
この正規表現は次のようになります。
犬
...簡単ですね。パターンには、文字 を含む任意の単語を指定することもできます
o
。このようなパターンを見つけるための正規表現は次のようになります。
\おお* _
(
この正規表現はここで試すことができます。)「一致」要件がより複雑になるにつれて、正規表現もより複雑になることがわかります。文字のグループを指定し、繰り返しパターンに一致させるための追加の表記形式があります。これについては、以下で説明します。しかし、テキスト内のパターンに一致するものが見つかったら、それに対して何ができるでしょうか? 最新の正規表現エンジンを使用すると、含まれているテキストから文字または文字のシーケンス (部分文字列) を抽出したり、削除したり、他のテキストに置き換えたりすることができます。一般に、正規表現はテキストの解析と操作に使用されます。たとえば、IP アドレスのように見える部分文字列を抽出して、それらの検証を試みることができます。あるいは、名前と電子メール アドレスを抽出してデータベースに保存することもできます。または、正規表現を使用して電子メール内の機密情報 (パスポート番号や電話番号など) を検索し、危険にさらされている可能性があることをユーザーに警告します。正規表現は、学ぶのは簡単ですが、習得するのが難しいまさに多用途のツールです。
「音楽を上手に演奏することと音楽を作成することには違いがあるのと同じように、正規表現を知ることと理解することには違いがあります。」 - Jeffrey E.F. Friedl、正規表現の習得
ステップ 2: 角括弧[]
理解しやすい最も単純な正規表現は、正規表現パターンとターゲット文字列の間の 1 文字ずつの一致を単純に検索する正規表現です。たとえば、猫を見つけてみましょう。
パターン:猫
string: 猫が車の下に逃げたときに切られました。
一致します: ^^
(
実際にどのように機能するか - ここを参照してください)
注意! すべての解決策は、可能な解決策としてのみここに示されています。正規表現では、一般的なプログラミングと同様に、同じ問題をさまざまな方法で解決できます。 ただし、厳密な文字ごとの比較に加えて、角括弧を使用して代替一致を指定することもできます。
パターン:カート[rt]
string: 猫が車の下に逃げたときに切られました。
一致: ^^^ ^^^
(
仕組み) 左角括弧と右角括弧は、指定された文字のいずれかと一致する必要があることを正規表現エンジンに伝えますが、一致するのは 1 文字だけです。たとえば、上記の正規表現では
cart
単語全体は検索されませんが、単語の一部のみが検索されます。
パターン:カート[rt]
string: 猫がカートの下を走ったときに切られました。
一致: ^^^ ^^^
(
仕組み) 角括弧を使用すると、角括弧内に含まれる文字のうち 1 つだけと一致するように正規表現エンジンに指示します。エンジンは文字 を見つけ
c
、次に文字 を見つけます
a
が、次の文字が
r
またはでない場合
t
、これは完全一致ではありません。が見つかった場合
ca
、または のいずれ
r
かが見つかった場合
t
、停止します。角括弧は、含まれている文字のうち 1 つだけを照合する必要があることを示しているため、それ以上の文字の照合は試行されません。見つかった場合は、次の単語内で
ca
検索し、シーケンスに一致するものがすでに見つかっているため停止します。
r
cart
car
トレーニングの目的:
地元の方言で翻訳できないダジャレの抜粋の
had
10パターンすべてに一致する正規表現を作成します。
Had
パターン:
文字列: ジムは、Bill が"had"を持っていましたが、"had had" を持っていました。「あった」が正しかった。
一致: ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^
(
可能な解決策をここで参照してください) 次の文にあるすべての動物の名前はどうでしょうか?
パターン:
string: コウモリ、猫、ネズミがバーに入ってきました...
一致: ^^^ ^^^ ^^^
(
考えられる解決策) またはさらに簡単: 単語を見つける
bar
か
bat
:
パターン:
string: コウモリ、猫、ネズミがバーに入ってきました...
一致: ^^^ ^^^
(
考えられる解決策) これで、多かれ少なかれ複雑な正規表現の書き方をすでに学びましたが、まだステップ 2 にすぎません。続けましょう!
ステップ 3: エスケープ シーケンス
前のステップでは、角括弧
[]
と、正規表現エンジンを使用して代替一致を見つけるのに角括弧がどのように役立つかについて学びました。しかし、開き角括弧と閉じ角括弧自体の形式で一致を見つけたい場合はどうすればよいでしょうか
[]
? 単語 の 1 文字ごとの一致を見つけたいときは
cat
、この文字シーケンス ( ) を正規表現エンジンに提供しました
cat
。
[]
同じ方法で 角括弧を見つけてみましょう。
パターン: []
文字列:正規表現を使用して [] と一致させることはできません。これでは後悔するでしょう!
一致します:
(
何が起こったのか見てみましょう) しかし、何かがうまくいきませんでした...これは、角括弧文字が、通常、何か他のものを示すために使用される特別な正規表現エンジン文字として機能し、角括弧自体に一致するリテラル パターンではないためです。ステップ 2 で思い出したように、これらは正規表現エンジンがそれらの間に含まれる文字のいずれかと一致できるように、代替一致を見つけるために使用されます。間に文字を入れないとエラーになる場合があります。これらの特殊文字と一致させるには、前にバックスラッシュ文字を付けてエスケープする必要があります
\
。バックスラッシュ (またはバックスラッシュ) は、メタ文字として使用するのではなく、文字通り次の文字を探すように正規表現エンジンに指示するもう 1 つの特殊文字です。
正規表現エンジンは、両方の文字の前にバックスラッシュ がある場合にのみ
[
文字を検索します。
]
パターン:\[\]
string: 正規表現を使用して [] と一致させることはできません。これでは後悔するでしょう!
一致します: ^^
(
今回何が起こったのか見てみましょう) さて、バックスラッシュ自体を見つけたい場合はどうすればよいでしょうか? 答えは簡単です。
\
バックスラッシュも特殊文字であるため、エスケープする必要があります。どうやって?バックスラッシュ!
パターン:\\
文字列: C:\Users\Tanja\Pictures\Dogs
一致します: ^ ^ ^ ^
(
実際には同じ例です) 特殊文字のみの前にバックスラッシュを付ける必要があります。他のすべての文字はデフォルトで文字通りに解釈されます。たとえば、正規表現は
t
文字通り
t
小文字のみに一致します。
パターン: t
文字列: tttt
一致します: ^ ^ ^ ^
(
例) ただし、このシーケンスは
\t
動作が異なります。タブ文字を検索するためのテンプレートです。
パターン: \t
文字列: tttt
一致します: ^ ^ ^
(
例) 一般的なエスケープ シーケンスには、
\n
(UNIX スタイルの改行) や
\r
(Windows スタイルの改行で使用
\r\n
) などがあります。
\r
は「キャリッジ リターン」文字と
\n
「ライン フィード」文字で、
どちらもテレタイプライターがまだ広く使用されていたときに ASCII 標準とともに定義されました。 他の一般的なエスケープ シーケンスについては、このチュートリアルで後ほど説明します。
それまでの間、いくつかの簡単なパズルで資料を統合しましょう。
正規表現を見つけて正規表現を書いてみてください ;) 結果は次のようになります。
パターン:
文字列: ...この正規表現 ` \[\] ` を正規表現と一致させますか?
一致します: ^^^^
(
解決策) できましたか? よくやった!次に、次のようにエスケープ シーケンスを検索するための正規表現を作成してみます。
パターン:
文字列: ` \r `、` \t `、および ` \n ` はすべて正規表現のエスケープ シーケンスです。
一致します: ^^ ^^ ^^
(
解決)
ステップ 4: ドットを使用して「任意の」文字を検索する.
前のステップで見たエスケープ シーケンス マッチング ソリューションを作成するときに、「バックスラッシュ文字とそれに続く他の文字をマッチングできるだろうか?」と疑問に思ったかもしれません... もちろん、それは可能です。(ほぼ) あらゆる文字と一致するために使用される別の特殊文字、ドット (ピリオド) 文字があります。その内容は次のとおりです。
パターン:。
文字列: ごめんなさい、デイブ。残念ながらそれはできません。
一致: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
(
例) エスケープ シーケンスに似たパターンのみを一致させたい場合は、次のようなことができます。
パターン:\\。
文字列: こんにちは、ウォルマートは私の孫です、彼の名前は「\n \r \t」です。
一致します: ^^ ^^ ^^
(
例) また、すべての特殊文字と同様、リテラルと一致させたい場合は
.
、その前に文字を付ける必要があります
\
。
パターン:\。
文字列: 戦争は平和です。自由は奴隷制です。無知は強さです。
一致します: ^ ^ ^
(
例)
ステップ 5: 文字範囲
記号は必要なく、テキスト内の文字だけを検索したい場合はどうすればよいでしょうか? それとも数字でしょうか?それとも母音?文字クラスとその範囲で検索することでこれを実現できます。
` \n `、` \r `、および ` \t `は空白文字、` \です。`、` \\ `、および ` \[ ` はそうではありません。
文字がテキスト内に目に見えるマークを作成しない場合、 文字は「空白」になります。 スペース「
」はスペース、改行、またはタブです。上記の文で、空白文字のみを表すエスケープ シーケンスを検索し、他のエスケープ シーケンスは検索したくない
\n
としましょう。どうすればこんなことができるでしょうか?
\r
\t
パターン: \\[nrt]
文字列: ` \n `、` \r `、および ` \t `は空白文字、` \です。`、` \\ `、および ` \[ ` はそうではありません。
一致します: ^^ ^^ ^^
(
例) これは機能しますが、あまり洗練された解決策ではありません。後で「フォーム フィード」文字のエスケープ シーケンスを照合する必要がある場合はどうすればよいでしょうか
\f
? (この記号はテキスト内の改ページを示すために使用されます。)
パターン: \\[nrt]
文字列: ` \n `、` \r `、` \t `、および ` \f `は空白文字、` \です。`、` \\ `、および ` \[ ` はそうではありません。
一致します: ^^ ^^ ^^
(
機能しない解決策) このアプローチでは、一致させたい各小文字を角かっこ内に個別にリストする必要があります。これを行うより簡単な方法は、文字範囲を使用して任意の小文字と一致させることです。
パターン: \\[az]
文字列: ` \n `、` \r `、` \t `、および ` \f `は空白文字、` \です。`、` \\ `、および ` \[ ` はそうではありません。
一致します: ^^ ^^ ^^ ^^
(
そして、これはすでに機能しています) 上記の例を考えると、文字範囲はご想像どおりに機能します。一致させる最初と最後の文字を角括弧で囲み、間にハイフンを入れます。たとえば、バックスラッシュの「セット」とから まで
\
の 1 文字だけを検索したい場合は、次のようにすることができます。
a
m
パターン: \\[am]
文字列: ` \n `、` \r `、` \t `、および ` \f `は空白文字、` \です。`、` \\ `、および ` \[ ` はそうではありません。
一致します: ^^
(
例) 複数の範囲を一致させたい場合は、単に角かっこで囲んで端から端まで配置します。
パターン: \\[a-gq-z]
文字列: ` \n `、` \r `、` \t `、および ` \f `は空白文字、` \です。`、` \\ `、および ` \[ ` はそうではありません。
一致します: ^^ ^^ ^^
(
例) その他の一般的な文字範囲には
A-Z
次のものがあります。
0-9
実際に試して、いくつかの問題を解決してみましょう。
0-9
16 進数には、文字だけでなく数字も含めることができます
A-F
。色の指定に使用する場合、16 進コードには最大 3 文字を含めることができます。正規表現を作成して、以下のリストから有効な 16 進コードを検索します。
パターン:
文字列: 1H8 4E2 8FF 0P1 T8B 776 42B G12
一致: ^^^ ^^^ ^^^ ^^^
(
解決策y
) 文字範囲を使用して、以下の文で 小文字の子音のみ ( を含む母音は選択しない) を選択する正規表現を作成します。
パターン:
文字列:壁はすべてt o t a lly 、to t a lly t allです。_ _ _ _ _ _ _ _ _ _
一致します: ^ ^ ^^^ ^ ^^ ^ ^^ ^ ^ ^ ^^^ ^ ^ ^^^ ^ ^^
(
解決)
ステップ 6: 「not」、キャレット、サーカムフレックス、キャレット... 記号^
実際、このシンボルには 9000 を超える名前があります :) しかし、話を簡単にするために、おそらく「not」に焦点を当てます。最後の問題に対する私の解決策は少し長くなります。「母音を除くアルファベット全体を理解する」と言うには 17 文字必要でした。もちろん、これを行うより簡単な方法があります。「not」記号を使用すると、パターンで指定されたものと一致してはなら
ない^
文字および文字の範囲を指定できます。上記の最後の問題に対するより簡単な解決策は、母音を表さない文字を見つけることです。
パターン: [ ^ aeiou ]文字列
: モール内の壁は、すべて、すべて、すべてです。_ _ _ _ _ _ _
一致します: ^^ ^^ ^^^^ ^^^^ ^^ ^^^ ^ ^^ ^ ^^^^^^ ^ ^^^^^ ^^^
(
例^
)角括弧内の左端の文字としての「not」記号は、
[]
角括弧内にない 1 つの (任意の) 文字と一致するように正規表現エンジンに指示します。これは、上記の正規表現が文の先頭のすべてのスペース、ピリオド
.
、カンマ
,
、および大文字にも一致することを意味します。
T
それらを除外するには、それらを角かっこで囲むこともできます。
パターン: [ ^ aeiou . , T ]文字列
:壁の中は完全に、完全に、完全に、すべてです。 _ _ _ _
一致します: ^ ^ ^^^ ^ ^^ ^ ^^ ^ ^ ^ ^^^ ^ ^ ^^^ ^ ^^
(
例)
注記この場合、以前に角括弧を使用せずにピリオドを検索したときのように、バックスラッシュでピリオドをエスケープする必要はありません。
[
角括弧内の多くの特殊文字は、左括弧文字ではなく左括弧文字を含め、文字通りに扱われます
]
(理由はわかりますか?)。バックスラッシュ文字
\
も文字通りには解釈されません。角括弧を使用してリテラルのバックスラッシュを照合する場合は
\
、その前に次のバックスラッシュを付けてバックスラッシュをエスケープする必要があります
\\
。この動作は、空白文字も角括弧内に配置して照合できるように設計されています。
パターン: [\t]
文字列: tttt
一致します: ^ ^ ^
(
例) 「not」記号は
^
範囲でも使用できます。文字
a
、
b
、
c
、
x
、
y
およびのみをキャプチャしたい場合は
z
、次のようにすることができます。
パターン: [abcxyz]
文字列: abc defghijklmnopqrstuvw xyz
一致: ^^^ ^^^
(
例) ...または、 との間に
ない文字を検索するように指定することもできます。
d
w
パターン: [^dw]
文字列: abc defghijklmnopqrstuvw xyz
一致: ^^^ ^^^
(
例)ただし、
気をつけて「ない」を付けて
^
。
[^ b-f]
「まあ、 を指定したので、 の後に小文字
a
か何かを取得する必要があると考えがちです
f
が、そうではありません。この正規表現は、文字、数字、句読点、スペースなど、その範囲にない文字と一致します。
パターン: [^dw]
文字列: abc defg h 。i 、 j - klmnopqrstuvw xyz の
一致: ^^^ ^ ^ ^ ^ ^^^
(
例)
タスクのレベルアップ:
^
で終わらない以下のすべての単語に一致するには、角かっこ内の「not」記号を使用します
y
。
パターン:
文字列: デイドッグ ホッグヘイボグベイ レイラブ
マッチ: ^^^ ^^^ ^^^ ^^^
(
解決策) 範囲と「not」記号を使用して、
^
1977 年から 1982 年までのすべての年 (両端を含む) を検索する正規表現を作成します。
パターン:
文字列: 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984
一致: ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^
(
解決策) 「not」記号文字ではないすべての文字を検索する正規表現を記述します
^
。
パターン:
文字列: abc1 ^ 23*()
一致: ^^^^ ^^^^^
(
解決)
ステップ 7: 文字クラス
文字クラスは文字範囲よりもさらに単純です。正規表現エンジンが異なれば利用可能なクラスも異なるため、ここでは主なものについてのみ説明します。(使用している正規表現のバージョンを確認してください。他にも存在する可能性があります。または、ここに示されているものとは異なる可能性があります。) 文字クラスは範囲とほぼ同じように機能しますが、「開始」値と「終了」値を指定することはできません。
クラス |
シンボル |
\d |
「数字」[0-9] |
\w |
「言葉の記号」[A-Za-z0-9_] |
\s |
「スペース」[ \t\r\n\f] |
「word」文字クラスは、
\w
さまざまなプログラミング言語で有効な識別子 (変数名、関数名など) にこの文字セットが必要になることが多いため、特に便利です。
\w
前に見た正規表現を簡略化するために 使用できます。
パターン: \\[az]
文字列: ` \n `、` \r `、` \t `、および ` \f `は空白文字、` \です。`、` \\ `、および ` \[ ` はそうではありません。
一致します: ^^ ^^ ^^ ^^
を使用すると、
\w
次のように書くことができます。
パターン: \\\w
文字列: ` \n `、` \r `、` \t `、および ` \f `は空白文字、` \です。`、` \\ `、および ` \[ ` はそうではありません。
一致します: ^^ ^^ ^^ ^^
(
例)
運を高めるための 2 つのタスク:
ご存知のとおり、Java では、識別子 (変数、クラス、関数などの名前) は、文字
a
-
zA
-
Z
、ドル記号
$
、またはアンダースコアでのみ始めることができます
_
。(
下線はもちろん悪いスタイルですが、コンパイラーはそれをスキップします、翻訳者注)。残りの文字は「単語」文字である必要があります
\w
。1 つ以上の文字クラスを使用して、次の 3 文字シーケンスの中から有効な Java 識別子を検索するための正規表現を作成します。
パターン:
文字列: __e $12 .x2 foo バー3mm
一致: ^^^ ^^^ ^^^ ^^^
(
解決策) 米国の社会保障番号 (SSN) は、XXX-XX-XXXX 形式の 9 桁の番号で、各 X には任意の数字を指定できます
[0-9]
。1 つ以上の文字クラスを使用して正規表現を作成し、以下のリストで正しくフォーマットされた SSN を検索します。
パターン:
文字列: 113-25=1902 182-82-0192 H23-_3-9982 1I1-O0-E38B
一致: ^^^^^^^^^^^
(
解決策)
RegEx: 正規表現をマスターするための 20 の短いステップ。パート 2. 正規表現をマスターするための 20 の短いステップ。パート 3. RegEx: 正規表現をマスターするための 20 の短いステップ。パート4。
GO TO FULL VERSION