2つの入力ファイルの列を含むファイルを作成したいと思います。
ファイル1は次のようになります。
11111111 abc12345 Y
22222222 xyz23456 Y
ファイル2:
11111111 abc12345
33333333 kbc34567
出力は次のようになります。
11111111 abc12345 Y
22222222 xyz23456 Y
33333333 kbc34567
次のことを試して重複項目を見つけることができましたが、最初のファイルと他のレコードの重複項目も同じ形式(最初、2番目、および3番目の列の間の同じスペース)でなければなりません。
awk 'FNR==NR{a[$1$2]=$1$2;next} ($1$2 in a) {print a[$1$2],$3}' file2 file1
答え1
i) 連結された最初と2番目のフィールド; ii) 3番目のフィールドを印刷しているため、スペースが変更されます。デフォルトでは、awk
スペースは出力フィールド区切り文字()として使用されるため、スペースはOFS
混乱します。簡単な解決策は、$0
行自体()をフィールドの代わりに配列に格納することです。
a[$1$2]=$0;
ただし、とにかくスクリプトは必要に応じて機能しません。 file2のfile1の行のみを印刷するため、file1にのみある行はすべてスキップされます。目的の出力に基づいて両方のファイルのすべての行を印刷し、file2の1行にfile1の最初の2つのフィールドと同じ最初の2つのフィールドがある場合は、file1の対応する行のみを印刷しようとしています。次の方法でこれを実行できますawk
。
awk 'FNR==NR{a[$1$2]=$0; print} !($1$2 in a) {print}' file1 file2
file1
これにより、配列の各行が保存され印刷されます。その後、file2
処理時に最初の2つのフィールドがないすべての行を印刷しますa
。
以下を使用してこれを実行することもできますsort
。
$ sort -uk1,2 file1 file2
11111111 abc12345 Y
22222222 xyz23456 Y
33333333 kbc34567
両方のファイルでスペースの量が等しいかどうかを確認する(例ではそうではありません)、これを達成するには、次のコマンドを使用します。
$ sed 's/ */\t/g' file1 file2 | sort -uk1,2
11111111 abc12345 Y
22222222 xyz23456 Y
33333333 kbc34567
答え2
ファイルサイズによっては、これが最も効率的なアプローチではないかもしれませんが、特定の状況ではうまくいくと思います。ファイルは特定の順序である必要はありませんが、常にFile2よりもFile1を優先する必要があります。
#!/bin/bash
# Make a list of the unique identifiers in each of the files, changing the whitespace in between into a comma.
awk '{print $1 "," $2}' File1 File2| sort | uniq |
# Loop through all the unique identifiers we just found
while read l; do
# Create a regular expression for each identifier to use as
# a search term, changing the comma into "any number of whitespaces"
searchterm=$(echo $l | sed 's/,/\\\s*/')
# if this pattern exists in File1
if $(grep -E "$searchterm" File1 >& /dev/null); then
# print it out
grep -E "$searchterm" File1
else
# otherwise, print it if it's in File2
grep -E "$searchterm" File2
fi
done
File3が必要な場合は、スクリプトとして保存してそこに出力を送信できます。
#copy to merge_uniq.sh
chmod +x merge_uniq.sh
merge_uniq.sh > File3
答え3
awk 'BEGIN{i=0} {if (!($1$2 in a)) {a[$1$2]=$0; index_array[i] =$1$2; i++} } END{for (j=0; j<i; j++) print a[index_array[j]]}' 1 2
11111111 abc12345 Y
22222222 xyz23456 Y
33333333 kbc34567