たとえば、現在のディレクトリに特定の拡張子を持つファイルがいくつあるかを計算したいとします。
私は以下を使用しました:
ls | grep ".txt" | wc -l
これは次のように機能します。
ls | grep ".txt*" | wc -l
しかし、なぜこれも機能しませんか?
ls | grep "*.txt" | wc -l
拡張の前にワイルドカードを使用するときにgrep式で機能しないような理由は何ですか?なぜ最後には動作しないのですか?
ベストアンサー1
$ ls *.txt
このコマンドは、シェルグローブを使用して始まるすべての名前を一覧表示します.txt
。
$ ls | grep "*.txt"
このコマンドは、現在の作業ディレクトリにあるすべての(隠されていない)ファイルを一覧表示し、その出力をに送信しますgrep
。これは正規表現に基づくファイル名と一致します/*.txt/
。
/*.txt/
この正規表現は、使用される正規表現のスタイルに応じて、次のパターンと一致することがあります。
* -- zero or more characters of any type (or possibly only a literal '*'), followed by
. -- exactly one character of any type, followed by
txt -- the literal string 'txt', followed by anything
正規表現で*
「0個以上の先行サブ式」を表すワイルドカードですが、シェルグロブワイルドカードとは異なります。関連して、.
これはピリオドではなく、1文字のワイルドカードです(?
シェルグローブのワイルドカードに似ています)。したがって、この式は(やはり正規表現のスタイルに応じて)、のいずれかと一致しますが、file.txt
実際sometxtfile
にphoto_of_a_txt_file.png
は一致しませんtxtfile
(前の文字がと一致しないためですtxt
)。したがって、txt
この正規表現を使用すると、ファイル名の先頭を除いてリテラル文字列がどこにでも表示されることを知ることが重要です。
.txt
次に終わるファイル名をキャプチャするより良い正規表現/\.txt$/
:
\. -- A literal .
txt -- The literal string 'txt'
$ -- End of input
ls
したがって、パイピングに固執する場合grep
(解析された出力がなぜ悪い考えなのかを説明する本を今すぐ読まないでくださいls
)、おそらく次のようにします。
$ ls | grep "\.txt$"
を使用している場合は、wc
そうする必要はありません。 grep
数えることができます:
$ ls | grep -c "\.txt$"