列がタブで区切られた異なる形式の2つのファイルがあります。の列をとcolumn1
比較する必要があります。一致する場合は、の値をの値に置き換える必要があります。試してみましたが、値を置き換えることはできません。以下のコードスニペットの提案を提供できますか?column2
file1
file2
column6
file1
column3
file2
awk
awk 'FILENAME == ARGV[1] {
m[$1,$2] = $6;
next;
}
{
if (($1,$2) in m) {
m[$6]= $3; print m[$6];
}
}' file1 file2
top few lines of file1
1201 12011 1 0 0 0 1
1202 12021 1 0 0 0 1
1203 12031 1 0 0 0 1
1204 12041 1 0 0 0 2
1207 12071 1 0 0 0 2
1209 12091 1 0 0 0 1
1210 12101 1 0 0 0 1
1212 12121 1 0 0 0 1
1213 12131 1 0 0 0 1
1214 12141 1 0 0 0 2
top few lines of file2
1201 12011 1
1202 12021 1
1203 12031 1
1204 12041 1
1206 NA 1
1207 12071 2
1208 NA 1
1209 12091 2
1210 12101 2
更新された内容を別のファイルに書きたいので、file2の値をfile1列に割り当てたいと思います。out.txt
編集する
コメントに基づいて次のコードを試しました。
awk '{
if (FNR==NR) {
a[FNR]=$1;b[FNR]=$2;c[FNR]=$3}
else {
if (a[FNR] == $1 && b[FNR] ==$2) {
$6=c[FNR]} else {$6=$6};
print $0;
}
}' file2 file1
この出力を得る
1201 12011 1 0 0 1 1
1202 12021 1 0 0 1 1
1203 12031 1 0 0 1 1
1204 12041 1 0 0 1 2
1207 12071 1 0 0 0 2
1209 12091 1 0 0 0 1
1210 12101 1 0 0 0 1
1212 12121 1 0 0 0 1
1213 12131 1 0 0 0 1
1214 12141 1 0 0 0 2
答え1
awk -F"\t" -v OFS="\t" '{
if (FNR==NR) {
a[FNR]=$1;b[FNR]=$2;c[FNR]=$3}
else {
if (a[FNR] == $1 && b[FNR] ==$2) {
$6=c[FNR]} else {$6=$6};
print $0
}
}' file2 file1
私はこれが仕事を終えると思います。まず、それぞれインデックスを使用して、file2の最初、2番目、および3番目の列をarrayに格納しますa
(file2の行のみ)。 Else (file1 の行のみに適用) 配列 sum の値を sum と比較します。一致する場合は、配列の6番目のフィールドを変更します。それ以外の場合は、値を同じ値に再割り当てし、区切り文字を 。b
c
FNR
FNR = NR
a
b
$1
$2
c
tab
答え2
大きなハンマーではなく別のawk
アプローチ
while read f1 f2 f3; do
sed -E -i "s/^($f1\s+$f2.*)([0-9]+)$/\1$f3/" file1;
done < file2
最後の数字が整数であると仮定します。そうでない場合は、([0-9])$
適切なキャプチャグループに変更する必要があります。
これは file1 の内部変更に依存するため、コピーが必要です。
答え3
awkスクリプトを見ると、各入力ファイルを異なる方法で処理する正しいアイデアが既にあります(ほとんどの場合、NR == FNR
数値比較が文字列比較よりも速いため、よりよく高速に動作することを確認しますが... ...何千もの入力がある場合)これが重要です(1つまたは2つのファイルの入力行数)。
ただし、スクリプトが目的の操作を実行できないようにするいくつかの問題があります。
間違った順序でファイルを読み込んでいます。 file1の行を出力して6列をfile2の列3に置き換えようとするので、まずfile2を読み込んで配列を作成する必要があります
m
(file2のインデックス、file2の$1,$2
値)。$3
。修正
m[$6]
後に印刷しています。最大1つの列が印刷されます。
次のようにしてみてください。
$ awk 'NR == FNR { m[$1,$2] = $3; next }
($1,$2) in m { $6 = m[$1,$2] }
1' file2 file1
1201 12011 1 0 0 1 1
1202 12021 1 0 0 1 1
1203 12031 1 0 0 1 1
1204 12041 1 0 0 1 2
1207 12071 1 0 0 2 2
1209 12091 1 0 0 2 1
1210 12101 1 0 0 2 1
1212 12121 1 0 0 0 1
1213 12131 1 0 0 0 1
1214 12141 1 0 0 0 2
またはNR == FNR
最初の行を元のFILENAME == ARGV[1]
。
各行file2
(読み取る最初のファイル - コマンドラインのファイル名引数の順序に注意してください)ごとに$ 3を配列に保存し、m
次の入力行にジャンプします。列の合計は、配列へのインデックス$1
として使用されます。$2
その後、読み取りfile1
(および後続の入力ファイルがある場合)が配列のインデックスである場合は、配列に格納されている値に($1,$2)
置き換えられます。$6
m
次に、変更の有無にかかわらず、現在の入力行を印刷します(モード自体は、「現在の1
入力行の印刷」を意味するawkイディオム/ショートカットです。「1」はtrueと評価され、デフォルトのジョブは「印刷」です。だから事実上「真なら印刷されます」)
注:サンプルの予想出力を提供していないため、出力が必要なものと一致していることを確認できません。通常、OPのサンプル出力をファイルに保存し、鉱山が一致するかどうかを使用または確認するのが好きdiff
ですcmp
。私のawkスクリプトの出力が一致します。私の説明あなたの質問で何を求めていますか?