web-dev-qa-db-ja.com

コマンドの引数としてbashで区切られたテキストファイルを解析する

テキストファイルを次のように分割しています。

field1,field2,field3 
xield1,xield2,xield3 
dield1,dield2,dield3 
gield1,gield2,gield3

これらの各列はプログラムのパラメーターになります。プログラムは各行で呼び出されます

私はループのようなものを望んでいました:

for $i in file
    command $field2 -x $field3 -PN -$field1 >> output
done

このようなことをbashで達成するための最良の方法は何でしょうか?

10
Dean
while IFS=, read xx yy zz;do
    echo $xx $yy $zz
done < input_file

これは、フィールドの数が一定であれば機能するはずです。 echoの代わりに、コマンドを使用してください。

7
coffeMug

whileを組み込みでreadを使用する必要があります。

while IFS= read -r line;do
    fields=($(printf "%s" "$line"|cut -d',' --output-delimiter=' ' -f1-))
    command "${fields[1]}" -x "${fields[2]}" ... # ${fields[1]} is field 2
done < your_file_here

これがどのように機能するか

  • cutステートメントは行を受け取り、-dで指定された区切り文字で分割します。
  • --output-delimiterは、cutが選択したフィールドを表示するために使用する区切り文字です。ここでは、スペースを選択して、異なるフィールドを配列fieldsに配置できるようにします。
  • 最後に、すべてのフィールド(フィールド1から最後まで)が必要です。ここで-f1-が役立ちます。
  • これで、配列変数fieldsにさまざまなフィールドが格納されました。構文${field[number]}を使用して、特定のフィールドにアクセスできます。ここで、numberは、Bashでの配列のインデックス付けがゼロベースであるため、必要な実際のフィールド番号より1つ少ない値です。

  • フィールドのいずれかに空白が含まれている場合、これは失敗します。

一定数のフィールドの場合

代わりに 1_CRの答え のようなものを実行できます。

while IFS= read -r line;do
    IFS=, read -r field1 field2 field3 <<-EOI
    $line
    EOI
    command "$field2" -x "$field3" ... 
done < your_file_here

上記は、よりうるさいように見えますが、Bashだけでなく、POSIX準拠のシェルでも機能します。

4
Joseph R.

readを適切に設定することにより、IFSを取得して各行を,の配列に分割できます。

while IFS=, read -r -a input; do
 printf "%s\n" "${input[0]}" "${input[1]}"
done < input.txt

したがって、上記の例では、0から始まるインデックスを使用して各配列要素にアクセスできます。

1
iruvar

このawkワンライナーはあなたが望むことをします:

_awk -F, '{cmd="echo " $2 " -x " $3 " -PN " $1 ">> output";  system(cmd)}' f.txt
_

echoをコマンドに置き換え、_f.txt_を繰り返し処理するファイルに置き換えます。

簡単な説明:_-F,_は_,_を区切り文字として設定します。 cmdはコマンドを作成し、system(cmd)はコマンドを呼び出します。

1
mkc

gnu sedも使用できます。

sed infile -e 's!^\([^,]*\),\([^,]*\),\([^,]*\)$!command \1 -x \2 -PN \3!e' >> output

sコマンドのeオプションの使用に注意してください

1
hildred