AWKを使用したリストに基づいたデータセットのフィルタリング

AWKを使用したリストに基づいたデータセットのフィルタリング

条件(リストに存在する場合)に基づいてデータフレームの行をフィルタリングしたいと思います。私はこれまでこれを試しました。ところで、予想外の結果が出ました。データはコピーされていますが理解できません

#!/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

elementawk変数ではありません。

シェル変数の値を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。最初のフィールドがこの配列のキーである場合は、行を印刷します。

関連情報