私は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の最大パラメータ制限に達する前に、必要なすべてのサーバー名がディレクトリに表示されるという事実は、実際の原因をさらに曖昧にします。