これらの奇妙な記号の文字列が Linux 上で何をするのか疑問に思いませんか?コマンドラインの魔法を与えてくれます。正規表現の呪文を唱えてコマンド ライン スキルをレベルアップする方法を教えます。
正規表現とは何ですか?
正規表現 (
regexes
) は、一致する文字シーケンスを検索する方法です。文字と記号を使用して、ファイルまたはストリーム内で検索されるパターンを定義します。正規表現にはいくつかの異なるフレーバーがあります。ここでは、一般的な Linux ユーティリティとコマンド
(検索パターンに一致する行を出力する
コマンド
grep
など) で使用されるバージョンを見ていきます。これは、プログラミング コンテキストでの
標準正規表現の使用
とは少し異なります。
書籍全体が正規表現について書かれているため、このチュートリアルは単なる入門書にすぎません。正規表現には基本正規表現と拡張正規表現がありますが、ここでは拡張正規表現を使用します。
grep
で拡張正規表現を使用するには、
-E
(拡張) オプションを使用する必要があります。これはすぐに飽きてしまうので、
egrep
コマンドが作成されました。の
egrep
コマンドはと同じです
grep -E
組み合わせれば、毎回
-E
オプションを使用する必要はありません。
もっと使いやすいと思ったら
egrep
、 あなたはできる。ただし、公式には非推奨であることに注意してください。私たちがチェックしたすべてのディストリビューションにはまだ存在していますが、将来的にはなくなる可能性があります。
もちろん、いつでも独自のエイリアスを作成できるため、好みのオプションが常に含まれています。
小さな始まりから
この例では、Geeks のリストを含むプレーン テキスト ファイルを使用します。多くの Linux コマンドで正規表現を使用できることに注意してください。それらをデモンストレーションするための便利な方法として
grep
を使用しているだけです。
ファイルの内容は次のとおりです。
オタク未満.txt
ファイルの最初の部分が表示されます。
単純な検索パターンから始めて、ファイル内で文字「o」が出現するかどうかを検索してみましょう。繰り返しますが、すべての例で
-E
(拡張正規表現) オプションを使用しているため、次のように入力します。
grep -E 'o' geeks.txt
検索パターンを含む各行が表示され、一致する文字が強調表示されます。制約なしで単純な検索を実行しました。文字が複数回出現する場合、文字列の末尾に出現する場合、同じ単語内に 2 回出現する場合、さらには文字列の隣に出現する場合でも問題ありません。
いくつかの名前には O が 2 つ付いていました。それらのみをリストするには、次のように入力します。
grep -E 'oo' geeks.txt
予想どおり、結果セットははるかに小さく、検索語は文字通りに解釈されます。これは、入力した内容、つまり 2 つの「o」文字以外の意味はありません。
今後は、検索パターンの機能がさらに増える予定です。
行番号とその他の grep トリック
grep
で一致するエントリの行番号をリストしたい場合は、
-n
(行番号) オプションを使用できます。これは
grep
トリックです。正規表現機能の一部ではありません。ただし、一致するエントリがファイル内のどこにあるかを知りたい場合もあります。
次のように入力します。
grep -E -n 'o' geeks.txt
使用できるもう 1 つの便利な
grep
トリックは、
-o
(一致のみ) オプションです。周囲のテキストではなく、一致する文字シーケンスのみが表示されます。これは、リストをすばやくスキャンして行の重複一致を探す必要がある場合に便利です。
これを行うには、次のように入力します。
grep -E -n -o 'o' geeks.txt
出力を最小限に抑えたい場合は、
-c
(カウント) オプションを使用できます。
次のように入力して、一致するファイル内の行数を確認します。
grep -E -c 'o' geeks.txt
代替オペレーター
二重「l」と二重「o」の両方の出現を検索する場合は、代替演算子であるパイプ (
|
) 文字を使用できます。左側または右側の検索パターンに一致するものを探します。
次のように入力します。
grep -E -n -o 'll|oo' geeks.txt
二重の「l」、「o」、またはその両方を含む行が結果に表示されます。
大文字と小文字の区別
次のように、代替演算子を使用して検索パターンを作成することもできます。
午前|午前
これは「am」と「Am」の両方に一致します。些細な例以外の場合、これはすぐに面倒な検索パターンにつながります。これを回避する簡単な方法は、
grep
で
-i
(大文字と小文字を無視) オプションを使用することです。
これを行うには、次のように入力します。
grep -E 'am' geeks.txt
grep -E -i 'am' geeks.txt
最初のコマンドは、3 つの一致が強調表示された 3 つの結果を生成します。 「Amanda」の「Am」も一致するため、2 番目のコマンドは 4 つの結果を生成します。
アンカリング
他の方法でも「Am」シーケンスを一致させることができます。たとえば、そのパターンを具体的に検索したり、大文字と小文字を無視して、シーケンスが行の先頭に出現する必要があると指定したりできます。
文字行または単語の特定の部分に出現するシーケンスを照合することを、アンカーと呼びます。キャレット (
^
) 記号を使用して、検索パターンが文字シーケンスが行の先頭にある場合にのみ一致と見なす必要があることを示します。
次のように入力します (キャレットが一重引用符の中にあることに注意してください)。
grep -E ‘Am’ geeks.txt
grep -E -i '^am' geeks.txt
これらのコマンドはどちらも「Am」に一致します。
次に、行末に 2 つの「n」が含まれる行を探してみましょう。
行の終わりを表すドル記号 (
$
) を使用して、次のように入力します。
grep -E -i 'nn' geeks.txt
grep -E -i 'nn$' geeks.txt
ワイルドカード
ピリオド (
.
) を使用して任意の 1 文字を表すことができます。
次のように入力して、「T」で始まり「m」で終わり、間に 1 文字があるパターンを検索します。
grep -E 'Tm' geeks.txt
検索パターンは、シーケンス「Tim」および「Tom」と一致しました。ピリオドを繰り返して特定の文字数を示すこともできます。
中央の 3 文字が何であるかは気にしないことを示すために、次のように入力します。
grep-E 'J...n' geeks.txt
「Jason」を含む行が一致して表示されます。
アスタリスク (
*
) を使用すると、直前の文字が 0 回以上出現する場合に一致します。この例では、アスタリスクの前にある文字はピリオド (
.
) であり、これは (再び) 任意の文字を意味します。
これは、アスタリスク (
*
) が、任意の文字の任意の数 (ゼロを含む) に一致することを意味します。
アスタリスクは、正規表現の初心者にとって混乱を招くことがあります。おそらく、これは通常、「何でも」を意味するワイルドカードとして使用されるためです。
ただし、正規表現では、
'c*t'
「cat」、「cot」、「coot」などとは一致しません。むしろ、「ゼロ個以上の「c」文字とそれに続く「t」と一致する」と解釈されます。 。」したがって、「t」、「ct」、「cct」、「ccct」、または任意の数の「c」文字と一致します。
ファイル内のコンテンツの形式がわかっているため、検索パターンの最後の文字としてスペースを追加できます。スペースはファイル内で姓と名の間にのみ表示されます。
したがって、次のように入力して、ファイルの名のみを検索に含めるように強制します。
grep -E 'J.*n' geeks.txt
grep -E 'J.*n' geeks.txt
一見すると、最初のコマンドの結果には奇妙な一致がいくつか含まれているように見えます。ただし、それらはすべて、使用した検索パターンのルールと一致します。
シーケンスは大文字の「J」で始まり、その後に任意の数の文字が続き、最後に「n」が続く必要があります。ただし、すべての一致は「J」で始まり「n」で終わりますが、一部の一致は期待どおりではありません。
2 番目の検索パターンにスペースを追加したため、意図したとおりの結果が得られました。つまり、「J」で始まり「n」で終わるすべての名が得られました。
文字クラス
大文字の「N」または「W」で始まるすべての行を検索したいとします。
次のコマンドを使用すると、行内のどこに出現しても、大文字の「N」または「W」で始まるシーケンスを持つ行と一致します。
grep -E 'N|W' geeks.txt
それは私たちが望んでいることではありません。以下に示すように、検索パターンの先頭に行頭アンカー (
^
) を適用すると、同じ結果セットが得られますが、理由は異なります。
grep -E '^N|W' geeks.txt
検索では、行内の任意の場所に大文字の「W」を含む行が一致します。また、大文字の「N」で始まるため、「No more」行とも一致します。行頭アンカー (
^
) は大文字の「N」にのみ適用されます。
大文字の「W」に行頭アンカーを追加することもできますが、この単純な例よりも複雑な検索パターンではすぐに非効率的になります。
解決策は、検索パターンの一部を括弧 (
[]
) で囲み、アンカー演算子をグループに適用することです。括弧 (
[]
) は、「このリストの任意の文字」を意味します。これは、(
|
) 代替演算子は必要ないので省略できることを意味します。
行頭アンカーをリスト内の括弧 (
[]
) 内のすべての要素に適用できます。 (行頭アンカーが括弧の外側にあることに注意してください)。
次のように入力して、大文字の「N」または「W」で始まる行を検索します。
grep -E '^[NW]' geeks.txt
これらの概念は、次のコマンド セットでも使用します。
次のように入力して、Tom または Tim という名前の人を検索します。
grep -E 'T[oi]m' geeks.txt
キャレット (
^
) が括弧 (
[]
) 内の最初の文字である場合、検索パターンはリストに表示されない文字を探します。
たとえば、「T」で始まり「m」で終わり、中央の文字が「o」ではない名前を検索するには、次のように入力します。
grep -E 'T[^o]m' geeks.txt
リストには任意の数の文字を含めることができます。次のように入力して、「T」で始まり「m」で終わり、途中に母音が含まれる名前を検索します。
grep -E 'T[aeiou]m' geeks.txt
間隔式
間隔式を使用して、一致する文字列内で先行する文字またはグループが検出される回数を指定できます。数値を中括弧 (
{}
) で囲みます。
数字は単独では具体的にその数字を意味しますが、その後にコンマ (
,
) を付けるとその数字以上を意味します。 2 つの数値をカンマ (
1,2
) で区切ると、最小値から最大値までの数値の範囲を意味します。
「T」で始まり、その後に少なくとも 1 つ (2 つ以下) の連続した母音が続き、「m」で終わる名前を検索したいと考えています。
そこで、次のコマンドを入力します。
grep -E 'T[aeiou]{1,2}m' geeks.txt
これは、「Tim」、「Tom」、および「Team」に一致します。
シーケンス「el」を検索したい場合は、次のように入力します。
grep -E 'el' geeks.txt
検索パターンに 2 番目の「l」を追加して、2 つの「l」を含むシーケンスのみを含めます。
grep -E 'ell' geeks.txt
これは次のコマンドと同等です。
grep -E 'el{2}' geeks.txt
「l」が「少なくとも 1 つ、2 つ以下」出現する範囲を指定すると、「el」および「ell」シーケンスと一致します。
これは、これら 4 つのコマンドのうちの最初の結果とは微妙に異なります。この場合、すべての一致は「el」シーケンス内のものを含む「el」シーケンスに対するものでした (1 つの「l」のみが強調表示されています)。
次のように入力します。
grep -E 'el{1,2}' geeks.txt
2 つ以上の母音のシーケンスをすべて検索するには、次のコマンドを入力します。
grep -E '[aeiou]{2,}' geeks.txt
エスケープ文字
ピリオド (
.)
が最後の文字である行を検索したいとします。ドル記号 (
$
) が行末アンカーであることがわかっているので、次のように入力します。
grep -E '.$' geeks.txt
ただし、以下に示すように、期待した結果は得られません。
前に説明したように、ピリオド (
.
) は任意の 1 文字と一致します。すべての行が文字で終わるため、結果ではすべての行が返されます。
では、実際の文字を検索したいだけの場合に、特殊文字がその正規表現機能を実行しないようにするにはどうすればよいでしょうか?これを行うには、バックスラッシュ (
\
) を使用して文字をエスケープします。
-E
(拡張) オプションを使用する理由の 1 つは、基本的な正規表現を使用するときに必要なエスケープが大幅に少なくなるからです。
次のように入力します。
grep -e '\.$' geeks.txt
これは、行末の実際のピリオド文字 (
.
) と一致します。
アンカリングと言葉
上記では行頭アンカー (
^
) と行末アンカー (
$
) の両方について説明しました。ただし、他のアンカーを使用して単語の境界を操作することもできます。
この文脈では、単語とは空白 (行の先頭または末尾) で囲まれた一連の文字です。したがって、辞書には載っていませんが、「psy66oh」も単語としてカウントされます。
単語アンカーの始まりは (
\<
) です。左、つまり単語の先頭を指していることに注意してください。名前が誤ってすべて小文字で入力されたとします。 grep
-i
オプションを使用すると、大文字と小文字を区別しない検索を実行し、「h」で始まる名前を見つけることができます。
次のように入力します。
grep -E -i 'h' geeks.txt
これにより、単語の先頭にあるものだけでなく、「h」が出現するすべての文字が検索されます。
grep -E -i '\<h' geeks.txt
これにより、単語の先頭にあるもののみが検索されます。
文字「y」でも同様のことをしてみましょう。単語の末尾にあるインスタンスだけを確認したいのです。次のように入力します。
grep -E 'y' geeks.txt
これにより、単語内に出現するすべての「y」が検索されます。
ここで、単語の終わりのアンカー (
/>
) (右側、つまり単語の終わりを指す) を使用して、次のように入力します。
grep -E 'y\>' geeks.txt
2 番目のコマンドは、望ましい結果を生成します。
単語全体を検索する検索パターンを作成するには、境界演算子 (
\b
) を使用できます。検索パターンの両端で境界演算子 (
\B
) を使用して、より大きな単語内にある必要がある一連の文字を検索します。
grep -E '\bGlenn\b' geeks.txt
grep -E '\Bway\B' geeks.txt
その他の文字クラス
ショートカットを使用して、文字クラスのリストを指定できます。これらの範囲インジケーターを使用すると、検索パターンにリストのすべてのメンバーを入力する必要がなくなります。
次のすべてを使用できます。
- AZ: 「A」から「Z」までのすべて大文字。
- az: 「a」から「z」までのすべての小文字。
- 0-9: 0 から 9 までのすべての数字。
- dp: 「d」から「p」までのすべての小文字。これらの自由形式のスタイルを使用すると、独自の範囲を定義できます。
- 2-7: 2 から 7 までのすべての数字。
検索パターンでは文字クラスを必要なだけ使用することもできます。次の検索パターンは、「J」で始まり、「o」または「s」が続き、さらに「e」、「h」、「l」、「s」のいずれかが続くシーケンスと一致します。
grep -E 'J[os][ehls]' geeks.txt
次のコマンドでは、
az
範囲指定子を使用します。
検索コマンドは次のように分解されます。
- H: シーケンスは「H」で始まる必要があります。
- [az]: 次の文字は、この範囲内の任意の小文字にすることができます。
- *: ここでのアスタリスクは、任意の数の小文字を表します。
- man: シーケンスは「man」で終わる必要があります。
次のコマンドにすべてをまとめます。
grep -E 'H[az]*man' geeks.txt
乗り越えられないものはない
一部の正規表現は、すぐに視覚的に解析することが困難になる場合があります。複雑な正規表現を記述する場合、通常は小さなことから始めて、機能するまでセクションをどんどん追加していきます。時間の経過とともに洗練される傾向があります。
最終バージョンから逆算してその動作を確認しようとすると、まったく異なる課題になります。
たとえば、次のコマンドを見てください。
grep -E '^([0-9]{4}[- ]){3}[0-9]{4}|[0-9]{16}' geeks.txt
これをどこから解き始めますか?最初から始めて、一度に 1 つのチャンクを取り上げます。
- ^: 行アンカーの開始位置。したがって、シーケンスは行の最初になければなりません。
-
([0-9]{4}[- ]):
括弧は、検索パターン要素をグループにまとめます。他の操作はこのグループ全体に適用できます (詳細は後ほど)。最初の要素は、0 から 9
[0-9]の範囲の数字を含む文字クラスです。したがって、最初の文字は 0 から 9 までの数字です。次に、数値 4{4}を含む間隔式があります。これは、数字であることがわかっている最初の文字に当てはまります。したがって、検索パターンの最初の部分は 4 桁になります。その後に、スペースまたは別の文字クラスのハイフン ([- ]) を続けることができます。 - {3}: 数値 3 を含む間隔指定子がグループの直後に続きます。これはグループ全体に適用されるため、検索パターンは 4 桁の数字にスペースまたはハイフンが続き、これを 3 回繰り返すことになります。
-
[0-9]:
次に、0 から 9 までの数字の範囲を含む別の文字クラスがあります
[0-9]。これにより、検索パターンに別の文字が追加されます。これには、0 から 9 までの任意の数字を指定できます。 - {4}: 数字の 4 を含む別の間隔式が前の文字に適用されます。これは、文字が 4 文字になり、そのすべてが 0 から 9 までの任意の数字になることを意味します。
- |: 代替演算子は、その左側にあるものはすべて完全な検索パターンであり、右側にあるものはすべて新しい検索パターンであることを示します。したがって、このコマンドは実際には 2 つの検索パターンのいずれかを検索します。最初のグループは 4 桁のグループが 3 つあり、その後にスペースまたはハイフンが続き、さらに 4 桁が追加されます。
- [0-9]: 2 番目の検索パターンは、0 から 9 までの任意の数字で始まります。
- {16}: 間隔演算子が最初の文字に適用され、すべて数字である 16 文字に変換されます。
したがって、検索パターンは次のいずれかを検索します。
-
4 桁の 4 つのグループ。各グループはスペースまたはハイフン (
-) で区切られます。 - 16 桁の 1 つのグループ。
結果を以下に示します。
この検索パターンは、クレジット カード番号の一般的な書き込み形式を探します。また、1 つのコマンドでさまざまなスタイルを見つけることができる多機能性もあります。
ゆっくりしていく
複雑さは通常、多くの単純性をボルトで結合したものです。基本的な構成要素を理解すると、効率的で強力なユーティリティを作成し、価値のある新しいスキルを開発できるようになります。





