awk と gsub を使用して、別の列に基づいて特定の列を変更します。

awk と gsub を使用して、別の列に基づいて特定の列を変更します。

数百万の行と列を持つファイル (file1) があります。データの例は次のとおりです。

"col1","col2","col3","col4","col5","col6"
"AAA",0,5,10,"BGB",50
"BBB",4,7,10,"BFD",76
"AAA",15,0,0,"BGB",20
"AAA",10,13,10,"DDD",23

col1 に AAA があるすべての行を検索し、次に col5 に BGB があるすべての行を取得します。最後に、col2、col3、col4、col6 のすべての値を 50% 減らします (セル値が 0 または空白の場合は無視します)。そして、ファイルのすべての行を印刷します。したがって、出力は次のようになります。

"col1","col2","col3","col4","col5","col6"
"AAA",0,2.5,5,"BGB",25
"BBB",4,7,10,"BFD",76
"AAA",7.5,0,0,"BGB",10
"AAA",10,13,10,"DDD",23

私は次のことを試しましたが、うまくいきませんでした(また、gsub で複数の列を使用する方法がわかりませんでした)

grep AAA file1 | awk -F "," '$5~/BGB/ {gsub($6,\substr($6,1,length($6)-1)*0.50\, $6}1'

答え1

awk は grep と同様にパターンを一致させることができるため、パイプラインで grep と awk が必要になることはほとんどありません。

できるだろう

 awk  '
    BEGIN {FS = OFS = ","}
    $1 ~ /AAA/ && $5 ~ /BGB/ {
        if ($2) $2 = $2 / 2
        if ($3) $3 = $3 / 2
        if ($4) $4 = $4 / 2
        if ($6) $6 = $6 / 2
    }
    1
' file

または、列をより動的に減らしたい場合は

awk -v "columns=2,3,4,6" '
    BEGIN {
        FS = OFS = ","
        n = split(columns, a, /,/)
        for (i=1; i<=n; i++) cols[a[i]]=1
    }
    $1 ~ /AAA/ && $5 ~ /BGB/ {
        for (c in cols) if ($c) $c = $c / 2
    }
    1
' file

関連情報