grepが私が望むより多くのファイルをアスタリスクで検索するのはなぜですか?

grepが私が望むより多くのファイルをアスタリスクで検索するのはなぜですか?

私はbashスクリプトに深く陥っています。

grep -Ech 'string1|string2' /server/directory/$servername_log_20150312* | awk ...

「引数が多すぎます」エラーが発生してset -xファイルを開いて、grepが次のファイルから検索しようとしていることがわかりました。

/server/directory/$servername_log_20150101.000001.log   # Notice the date disparity.

文字列の各文字列は、$servernameループ内で繰り返される値を使用して正しく拡張されます。 grepが私が指定した文字列で始まるファイル名に制限されないのはなぜですか?

答え1

質問

サーバー名を定義することから始めましょう。

$ servername=SomeName

今試してください:

$ echo "$servername_log_20150312"

$

(a)下線はシェル変数名の有効な文字であり、(b)下線を定義したことがないため、上記は何も返しませんservername_log_20150312

さて、次のことを考えてみましょう。

/server/directory/$servername_log_20150312*

変数が展開されると、次のようになります。

/server/directory/*

パス名拡張後、上記の内容はディレクトリ内のすべてのファイルになります。

2つのソリューション

この種の作業は非常に一般的であるため、シェルには変数の中括弧表記があります。

$ echo "${servername}_log_20150312"
SomeName_log_20150312

次の文字から名前を分離する他の方法も可能です。

$ echo "$servername""_log_20150312"
SomeName_log_20150312

文書

これ以降、man bash変数名には英数字とアンダースコアを組み合わせて使用​​できますが、必ず英字で始める必要があります。

   name   A word consisting only of alphanumeric characters  and  underscores,  and
          beginning  with  an alphabetic character or an underscore.  Also referred
          to as an identifier.

POSIX変数名の実装に制限を依存させます。シェルが名前に英数字と下線を付けるように要求しますが、=NULとNULを除くすべてを許可するオプションをシェルに提供するようです。

答え2

@john1024が私のスクリプトのエラーを正しく指摘しました。 grepコマンドを実行すると、シェルは期待どおり$servername_log_20150312に変数を見つけません$servername

これを相殺すると"$servername"問題が解決します。

grepへの入力に予想されるサーバー名がすべて表示されるため、grepが奇妙に動作するようです。ただし、これは実際には変数が見つからず、デフォルトでは$servername_log_20150312ディレクトリ全体を検索するため、トリックです。 grepの最大パラメータ制限に達する前に、必要なすべてのサーバー名がディレクトリに表示されるという事実は、実際の原因をさらに曖昧にします。

関連情報