回答:
正規表現のアスタリスクは、「直前の要素に0回以上一致する」ことを意味します。
あなたの特定のケースではgrep 'This*String' file.txt
、あなたは「ねえ、grep、私に単語を一致させThi
、その後にs
ゼロ回以上小文字を続け、その後に単語を続けてください」と述べようとしていますString
。小文字s
はどこにも見つからないためExample
、grepは無視しThisExampleString
ます。
の場合、grep '*String' file.txt
「grep、単語の前にある空の文字列(文字通り何もない)に一致するか」と言っていますString
。もちろん、そうでThisExampleString
はありません。(他の可能な意味があります-E
-フラグを付けても付けなくてもこれを試すことができます-しかし、どの意味もここで本当に望んでいるようなものではありません。)
これ.
は「任意の1文字」を意味するので、次のようにできますgrep 'This.*String' file.txt
。これで、grepコマンドはそれを正しく読み取ります。This
その後に任意の文字(ASCII文字の選択と考えることができます)が何度も繰り返され、その後にが続きString
ます。
*
特殊な文字であり、それが引用されたか、このような例のためにエスケープする必要がありますgrep 'This*String' file.txt
か、この:grep This\*String file.txt
予期しない結果に驚くことではないし。
strace grep .* file.txt |& head -n 1
とstrace grep '.*' file.txt |& head -n 1
。また、実際にgrep
は任意のUnicode文字(例:echo -ne ⇏ | grep ⇏
出力⇏
)でも動作します
bash
。これは、最初にbash
その特殊文字を解釈し、すべての拡張が実行された後にのみ、生成されたプロセスにパラメーターを渡すことを意味します。-----例えばbashで、このコマンドは:grep This.\*String file.txt
出現します/bin/grep
:これらのパラメータ0でgrep
、1:This.*String
2: file.txt
。Bashがバックスラッシュを削除し、最初にエスケープ*
されたものが文字通り渡されたことに注意してください。
grep This.*String file.txt
は通常動作することです。これは、おそらくシェルのワイルドカード式に一致するファイルがないためですThis.*String
。このような場合、デフォルトではBashは文字列を含む引数を渡します*
。
*
BRE 1秒、ERE 1秒、PCRE 1秒のメタ文字は、以前にグループ化されたパターンの0回以上の出現(グループ化されたパターンが*
メタ文字の前にある場合)、以前の文字クラスの0回以上の出現(文字クラスが*
メタ文字の前)または前の文字の0回以上の出現(グループ化されたパターンも文字クラスも*
メタ文字の前にない場合);
これは、グループ化されたパターンまたは文字クラスが先行していないメタ文字であるThis*String
パターンでは、*
メタ文字*
が前の文字(この場合はs
文字)の0回以上の出現と一致することを意味します。
% cat infile
ThisExampleString
ThisString
ThissString
% grep 'This*String' infile
ThisString
ThissString
任意の文字の0回以上の出現に.
一致させるには、任意の文字に一致するメタ文字の0回以上の出現に一致させる必要があります。
% cat infile
ThisExampleString
% grep 'This.*String' infile
ThisExampleString
*
BREおよびERE のメタキャラクターは常に「貪欲」です。つまり、最長一致と一致します。
% cat infile
ThisExampleStringIsAString
% grep -o 'This.*String' infile
ThisExampleStringIsAString
これは望ましい動作ではない可能性があります。そうでない場合は、grep
(-P
オプションを使用して)のPCREエンジンをオンにし、?
メタキャラクターを追加できます。メタキャラクターは、*
および+
メタキャラクターの後に配置すると、貪欲度を変更する効果があります。
% cat infile
ThisExampleStringIsAString
% grep -Po 'This.*?String' infile
ThisExampleString
1:基本的な正規表現、拡張正規表現、およびPerl互換の正規表現
*
シェルのグロビング文字(「ワイルドカード」)と正規表現のメタ文字の両方に特別な意味があります。両方を考慮に入れる必要がありますが、正規表現を引用する場合は、シェルがそれを特別に処理することを防ぎ、変更せずにに渡すことができgrep
ます。概念的には似ていますが*
、シェルにとっての意味は、シェルにとっての意味とはかなり異なりgrep
ます。
*
ワイルドカードとしてます。あなたが言った:
式が引用符で囲まれているかどうかは関係ありません。
それは、コマンドを実行したときにたまたまあるディレクトリに存在するファイルに依存します。ディレクトリ区切り文字を含むパターンの/
場合、システム全体に存在するファイルによって異なる場合があります。あなたは、常に必要があります引用のための正規表現をgrep
-そして単一引用符は、通常best--ある場合を除き、あなたは、あなたがして大丈夫ですされている可能性の驚くべき変換の9種類のそれ以外の場合は実行するシェルの前に実行するgrep
コマンドを。
引用符で囲まれ*
ていない文字をシェルが検出すると、「ゼロ以上の任意の文字」を意味し、その文字を含む単語を、パターンに一致するファイル名のリストで置き換えます。(で始まるファイル名は除外されている-あなたのパターンがない限り、それ自体で始まるか。あなたはとにかくそれらを含めるようにシェルを設定した)これはとして知られているグロブ -そしてまた、名によってファイル名展開とパス名展開。.
.
の効果grep
は通常、最初に一致するファイル名が正規表現として解釈されます-正規表現ではないことが人間の読者には明らかであっても、他のすべてのファイル名はglobは、一致を検索するための内部のファイルと見なされます。(リストは表示されません。リストは不透明に渡されます。grep
。ます。)これが発生することはほとんどありません。
これが時々問題にならない理由-そしてあなたの特定のケースでは、少なくとも今のところ問題はありません- 以下のすべてが当てはまる場合、それは*
放置されます:
名前が一致するファイルはありませんでした。 ...または、シェルでグロビングを無効にしました。通常、set -f
または同等のものを使用しset -o noglob
ます。しかし、これは一般的ではなく、おそらくあなたがそれをしたことを知っているでしょう。
*
一致するファイル名がない場合、デフォルトの動作をそのままにするシェルを使用しています。これは、おそらく使用しているBashの場合ですが、すべてのBourneスタイルのシェルではそうではありません。(たとえば、人気のあるシェルZshのデフォルトの動作は、グロブが(a)展開するか、(b)エラーを生成するかのいずれかです。)または、シェルのこの動作を変更しました。シェル全体。
他の方法では、一致するファイルがない場合にグロブを何も置き換えないようにすることも、この状況でエラーメッセージを表示して失敗することもシェルに伝えていません。Bash では、それぞれ、nullglob
またはfailglob
シェルオプションを有効にすることで行われます。
#2と#3に依存することもできますが、#1に依存することはほとんどありません。grep
引用符で囲まれていないパターンで動作するコマンドは、ファイルが異なる場合や、別の場所から実行すると動作しなくなる場合があります。正規表現を引用すれば、問題はなくなります。
grep
コマンドは*
数量詞として扱います。他の回答-ものなどSergiy Kolodyazhnyyによるとコスによって多少異なる方法で、この質問のこの局面--alsoアドレス、。ですから、まだ読んでいない人には、この回答の残りの部分を読む前または読んだ後に読むことをお勧めします。
*
がそれをgrepに変換すると仮定します(これにより引用が確実になるはずです)grep
、その前にある項目が正確に1回発生する必要はなく、何度も発生する可能性があることを意味します。それでも一度は発生する可能性があります。または、まったく存在しない可能性があります。またはそれを繰り返すこともできます。これらの可能性のいずれかに適合するテキストが照合されます。
「アイテム」とはどういう意味ですか?
単一の文字。以来b
一致リテラルはb
、b*
ゼロまたはそれ以上の一致b
従って、Sをab*c
一致ac
、abc
、abbc
、abbbc
、等
同様に、任意の文字に一致するため.
、.*
ゼロ個以上の文字と一致する1ので、a.*c
マッチac
、akc
、ahjglhdfjkdlgjdfkshlgc
、でもacccccchjckhcc
、などまたは
文字クラス。以降[xy]
マッチx
またはy
、[xy]*
それぞれがいずれかのあるマッチがゼロ個以上の文字x
又はy
、従ってp[xy]*q
一致pq
、pxq
、pyq
、pxxq
、pxyq
、pyxq
、pyyq
、pxxxq
、pxxyq
、など
これはまたして適用されるフォーム速記のような文字クラスのを\w
、\W
、\s
、と\S
。は\w
任意の単語文字に\w*
一致するため、0個以上の単語文字に一致します。または
グループ。ため\(bar\)
マッチbar
、\(bar\)*
マッチは、ゼロまたはそれ以上bar
の、従ってfoo\(bar\)*baz
一致foobaz
、foobarbaz
、foobarbarbaz
、foobarbarbarbaz
、等
と-E
や-P
オプション、grep
としてあなたの正規表現として扱いEREやPCREをむしろとしてよりも、それぞれBRE、その後、グループが囲まれている(
)
代わりに、\(
\)
ように、あなたが使用したい、(bar)
代わりに\(bar\)
とfoo(bar)baz
の代わりにfoo\(bar\)baz
。
man grep
最後に、BREとERE構文の合理的にアクセス可能な説明を示しgrep
、最初に受け入れるすべてのコマンドラインオプションを一覧表示します。そのマニュアルページをリソースとしてお勧めします。また、GNU Grepのドキュメントとこのチュートリアル/リファレンスサイト(上記のいくつかのページにリンクしています)もお勧めします。
テストと学習用 grep
ために、パターンでファイル名を付けずに呼び出すことをお勧めします。次に、端末から入力を受け取ります。行を入力してください。エコーバックされる行は、パターンが一致したテキストを含む行です。終了するには、入力の終わりを示す行の先頭でCtrl+ Dを押します。(または、ほとんどのコマンドラインプログラムと同じようにCtrl+ Cを押すことができます。)例:
grep 'This.*String'
--color
フラグを使用すると、grep
と、正規表現に一致する行の特定の部分が強調表示されます。これは、正規表現の機能を理解するためと、一度行ったときに探しているものを見つけるための両方に非常に役立ちます。デフォルトでは、Ubuntuユーザーはコマンドラインからgrep --color=auto
実行grep
したときに実行する(この目的には十分です)ようにするBashエイリアスを持っているため、--color
手動で渡す必要すらありません。
1 したがって.*
、正規表現では*
、シェルグロブの意味を意味します。しかし、違いがあることであるgrep
自動的にマッチ含む行を印刷しどこでもそれが持っている一般的に不要ですので、その中に.*
正規表現の先頭や末尾。
* != any number of unknown characters
。ドキュメントを読んでください)