
ワイルドカード文字「*」を使用して、すべての .txt ファイルを grep したいと考えました。
このコマンド (および引用符「 」なし) を試しましたが、失敗しました。
ls | grep "*.txt"
興味深いのは、ディレクトリ内の.txtファイルに対応する別の文字をgrepコマンドに入れると、それが機能することです。
>>ls | grep s*.txt
sample.txt
それが機能することはわかっていますls *.txt
が、grep コマンドの性質に少し驚きました。なぜこのようなことが起こるのか、誰か教えてくれませんか?
grep が正規表現を使用するためでしょうか。助けてください。
答え1
正規表現では、*
は「前の項目の任意の数」を意味し、シェル パターンのように「任意の数の任意の文字」を意味するわけではありません。 および は.
「任意の 1 文字」を意味します。したがって、「任意のものの後にリテラル.txt
」が続くものを検索するには、 を使用します.*\.txt
。または\.txt
、通常、正規表現の一致は行内の任意の場所で一致を検索するため、 のみを使用します。また、は\.txt
のようなファイル名にも一致します。 は末尾にある必要がないためfoo.txtgz
です。パターンを行末にロックする必要があります。.txt
\.txt$
実装と、基本正規表現 ( ) を使用しているか拡張正規表現 ( ) を使用しているかに応じて、正規表現*.txt
は無意味、エラー、またはリテラルのアスタリスクを検索します。使用しないことをお勧めします。grep
grep -E
一方、s*.txt
は「任意の数の文字s
、任意の 1 文字、リテラルtxt
」を検索します。これはより有効な正規表現ですが、それでも一致しませんsample.txt
。
代わりに、2 番目のコマンドでは、 がs*.txt
引用符で囲まれていないため、シェルはを見るs*.txt
前にを展開します。一致するファイルが だけの場合、の出力でそのファイルを探します。(一致するファイル名が複数ある場合、最初のファイル名がパターンとして取得され、残りは が読み取るファイル名として取得されます。その場合、パイプからの入力は無視されます。)grep
sample.txt
grep
ls
grep
しかし、ls
ファイルのリストも取得できるので、
ls | grep '\.txt'
ファイルを取得するには.txt
、おそらく
ls *.txt
その代わり。
答え2
これは正規表現を使用しているためですgrep
(実際、re
名前の は正規表現の略です。ググローバルr規則的なe表現pリント)。
正規表現のワイルドカードは、シェルのグロビングのワイルドカード*
とは異なります。*
正規表現では、*
「0個以上の前に定義されたオブジェクト」を意味します。ただし.
、またワイルドカードは「1 文字」を意味します。
シェル グロブでは、*
「0 個以上の文字」を意味します。 .
ワイルドカードではありません。
grep
パターン を検索する場合"*.txt"
、ゼロ個以上の任意の文字の後に 1 文字以上が続き、その後にリテラル文字列 が続くものを検索しますtxt
。
grep
パターン"s*.txt"m you are looking for a literal
s , followed by zero or more
s s, followed by any character, followed by the literal string
txt`を検索する場合。
このため、正規表現には、 という共通の表現が見られます。.*
これは、「任意の文字 1 個に続いて任意の文字が 0 個以上続く」という意味です。正規表現は、「文字 0 個以外の文字の任意の組み合わせ」を表します。
ls *.txt
シェルに「glob パターンに一致するファイル名を検索し*.txt
、ここにリストして、コマンドの引数として指定してください」と指示する場合ls
。
答え3
grepはファイルを検索することに注意してくださいコンテンツ最初の引数は検索パターンであり、他の引数は検索するファイルとして解釈されます。
grep -H -o
フラグを使用したり、grep
スクリプト内に入れて実行したりして、bash -x script
引数として渡される前にシェルグロブがどのように展開されるかを確認すると、より明確になります。