他の列の条件に応じて、1列の値を変更します。

他の列の条件に応じて、1列の値を変更します。

次のように、6つの列を含む一連の.txtファイルがあります。

-44.2584 0.2603  42.7879 6 0.1 Precentral_L
49.3816  5.3947  40.4102 6 0.1 Precentral_R
-22.5897 9.5277  54.8691 6 0.1 Frontal-Sup_L
26.0365  32.0674 36.7889 6 0.1 Frontal-Sup_R

行数はファイルごとに異なります。 4列目(6)の条件を変更したいです。ラベルが「R」の場合は1に変更します。簡単なコマンドがありますか?

ベストアンサー1

$ awk '$6 ~ /_R$/ { $4 = 1 }1' input.txt 
-44.2584 0.2603  42.7879 6 0.1 Precentral_L
49.3816 5.3947 40.4102 1 0.1 Precentral_R
-22.5897 9.5277  54.8691 6 0.1 Frontal-Sup_L
26.0365 32.0674 36.7889 1 0.1 Frontal-Sup_R

6列がで終わったら、_R$ 4列をに変更します1。最後の awk スクリプトは1true と評価され、awk が基本操作であるprint.

結果をstdoutとして印刷するのではなく、入力ファイルを編集する必要があり、GNUバージョンのawkを使用している場合は、gawkinplaceライブラリを使用できます。例えば

awk -i inplace -v INPLACE_SUFFIX=.bak '$6 ~ /_R$/ { $4 = 1 }1' ./*.txt 

GNU awkがない場合は、各入力ファイルの出力を一時ファイルに書き込み、名前を元のファイルに変更する必要があります。または、出力ファイルを別のディレクトリに書き込み、元のファイルと変更されたファイルを保持します。ディスク容量が不足していない限り、ファイルの元のコピーを上書きするのは一般的に悪い考えです。後で元のファイルを削除できます。ただし、バックアップやスナップショットがないと削除を取り消すことはできません)

$ mkdir out

$ awk -v OUTDIR=./out '
    function basename(f) { sub(".*/", "", f); return f }
    $6 ~ /_R$/ { $4 = 1 }
    { print > OUTDIR "/" basename(FILENAME) }' ./*.txt

$ cat out/input.txt 
-44.2584 0.2603  42.7879 6 0.1 Precentral_L
49.3816 5.3947 40.4102 1 0.1 Precentral_R
-22.5897 9.5277  54.8691 6 0.1 Frontal-Sup_L
26.0365 32.0674 36.7889 1 0.1 Frontal-Sup_R

FILENAME現在処理中のファイルの名前を含む組み込みのawk変数。 awkには組み込み関数がないため、awkの関数のみを使用してファイル名からパスを削除する単純なbasename()関数を作成する必要がありました。sub()リダイレクトはシェルでの動作と同様に awk で動作します。

おすすめ記事