条件(リストに存在する場合)に基づいてデータフレームの行をフィルタリングしたいと思います。私はこれまでこれを試しました。ところで、予想外の結果が出ました。データはコピーされていますが理解できません
#!/bin/bash
arr_country=(AL AD AM AT BY BE BA BG CH)
for element in "${arr_country[@]}"
do
awk -F '\t' '{if($1==$element){print}}' abc.txt >>xyz.txt
done
echo
echo "Data Transferred"
サンプル・データ・セットには複数の国に関する情報が含まれ、最初の列は国名を表します。与えられた配列に基づいてデータセットのサブセットを作成したいと思います。
答え1
element
awk
変数ではありません。
シェル変数の値をawk
スクリプトにインポートするには、次のようにします。
awk -v variable="$value" '{ script goes here }'
上記の例では、という変数はvariable
という名前のシェル変数の値を取得しますvalue
。プレフィックスなしでスクリプトvariable
で使用できます。awk
$
$
変数の前に in を付けると、awk
変数の値が正の整数であり、現在の入力レコードの特定のフィールドを参照すると仮定されます。$element
たとえば、この式はフィールド番号の値を提供しますelement
(たとえば、$1
最初のフィールドの値を提供し、$NF
最後のフィールドの値を提供します。ここで、NF
現在のレコードのフィールド数を表す組み込み変数です)。
element
コードに設定しないと、awk
行全体に展開さ$element
れます。$0
タブ区切りの最初のフィールドが行の唯一の項目である場合、コードは行全体を印刷します。
スクリプトawk
を次のように短縮することもできます。
awk -F '\t' -v e="$element" '$1 == e'
または、コンテンツ全体を次のように置き換えることもできます。
arr_country=(AL AD AM AT BY BE BA BG CH)
( IFS='|'; grep -E "^(${arr_country[*]})\>" ) <abc.txt >xyz.txt
または、
grep -E '^(AL|AD|AM|AT|BY|BE|BA|BG|CH)\>' <abc.txt >xyz.txt
パラメータ${arr_country[*]}
置換は、の最初の文字で区切られた配列値で構成される単一の文字列に展開されます$IFS
。これにより、上記の2番目の正規表現と同じ正規表現が生成されますgrep
。 \>
単語の終わりの幅がゼロの空白と一致します(行の先頭^AA\>
と一致しますAA
が、行の先頭と一致しませんAAA
)。
唯一の違いは、シェルループソリューションと比較して結果の順序が異なる可能性があることですawk
。
シェルループを削除するさまざまな方法(デフォルトと仮定$IFS
):
arr_country=(AL AD AM AT BY BE BA BG CH)
awk -v c="${arr_country[*]}" -F '\t' '
BEGIN { n=split(c,a," "); for (i=1;i<=n;++i) country[a[i]] }
$1 in country' <abc.txt >xyz.txt
arr_country
ここでは、スペースで区切られた文字列の要素をawk
変数のコードに割り当てますc
。入力から読み取りを開始する前に、c
文字列は複数の部分に分割され、各部分は連想配列のキーで作成されますcountry
。最初のフィールドがこの配列のキーである場合は、行を印刷します。