ループ内の変数にgrepを使用する

ループ内の変数にgrepを使用する

grepの結果をループ内の変数として保存するのに問題があります。

while read file;do
  Server=$(echo $file | awk '{ print $1 }')
  FDate=$(echo $file | awk '{ print $2 }')
  ST=$(cat foobar | grep $Server | awk '{ print $3 }')
  #ST=$(grep $Server foobar | awk '{ print $3 }')

  echo "Server = $Server"
  echo "FDate = $FDate"
  echo "ST = $ST"

done < inputfile

最初のST varは、反復ごとに「Usage:grep [Option] ... Pattern [File]」出力を提供します。これは、コマンドが正しく読み取られていないことを意味します。

コメントアウトされた2番目のST変数は実際にスクリプト全体を中断し、エコーを試みると他のすべての変数が空になります。

これで、コマンドラインで同じことをしようとするとうまくいきます。

$ testme=$(cat foobar | grep Big | awk '{ print $3}'
$ echo "$testme"
tada

だから私の質問は、このgrepコマンドを変数に保存する方法です。パターンマッチングには可能な結果が1つしかないため、複数のマッチングについて心配する必要はありません。ただし、ループ内の各サーバーは、列3(tada、tada1、tada2)に異なる文字列を持つことができます。

編集する:

入力ファイルには、複数の列を含むサーバーのリストがあります。現在行の列1にリストされているサーバーをインポートし、foobarファイルから一致するものを検索し、列3から文字列を取得します。

「使用」メッセージが表示されるにもかかわらず、スクリプトが実際に機能していることがわかりました。入力ファイルの一部のサーバーエントリがfoobarファイルにまだ表示されていないため、grepに一致はありませんが、まだawkにパイプしようとする可能性があります。よくわかりません。

しかし、私はまだ「使用」メッセージを削除したいと思います。私の考えでは「set -opipelinefail」がうまくいくかもしれませんが、そうしない方が良いです。

ベストアンサー1

while read file;do                                       # 1
  Server=$(echo $file | awk '{ print $1 }')              # 2
  FDate=$(echo $file | awk '{ print $2 }')               # 3
  ST=$(cat foobar | grep $Server | awk '{ print $3 }')   # 4
  #ST=$(grep $Server foobar | awk '{ print $3 }')        # 5

grep少なくとも検索パターンが必要です(またはそれに対応するオプションを提供するかオプション-e)。したがって、空の場合は、4行と5行の引用符なしの内容-f$Server$Server噴射(あなたも見ることができます いつ二重引用符が必要ですか?)、そして

  • 行4grepにはパラメータはありません。必須パラメーターがない場合は、使用法の説明が印刷されます。
  • 行5では、grep単一のパラメータを取得してfoobarパターンにします。基本的には標準入力から読み込み、ループ内にはループと同じ標準入力があるので、そこからすべてを読みます。

さて、ループ全体を見ると、次の質問が考えられます。シェルループを使用してテキストを処理するのはなぜ悪い習慣と見なされますか?少なくともある程度単純化することができます。read入力はフィールド自体に分割できるため、コマンド置換を削除できます。

これにより、おそらく値のいずれかまたは両方が空の場合に対処する必要があります。そして、awkも作業を実行できるので、grep次のようにしましょう。

while read server fdate; do
    if [ -z "$server" ] || [ -z "$fdate" ]; do
        continue
    fi
    ST=$(awk < foobar -v server="$server" '$0 ~ server { print $3 }')

    echo "server $server fdate $fdate ST $ST"
done < inputfile

(または最終的に何をしたいかに応じて、全体をawkプログラムに置き換えます。)

おすすめ記事