File1には8つの列があります。列3と4は、rs | 860 rs | 756のようなペアを形成し、このペアに関連する値は列8にあります。
bb yy rs|860 rs|756 xx aa 0.7 2234
bb yy rs|310 rs|260 xx aa 0.3 9838
bb yy rs|110 rs|77 xx aa 0.5 2291
bb yy rs|756 rs|860 xx aa 0.4 2269
bb yy rs|110 rs|77 xx aa 0.9 1112
bb yy rs|756 rs|860 xx aa 0.8 3269
bb yy rs|233 rs|79 xx aa 0.4 1397
bb yy rs|79 rs|233 xx aa 0.7 1397
列3と4、または4と3のペアは同じように処理する必要があります(例:rs | 860 rs | 756 == rs | 756 rs | 860)。次に、1行のペアが4行と6行にも現れることがあります(またはその逆)。簡単に言えば、AB = BA = BAです。まず、col3とcol4を行ごとにソートして、AB = AB = ABのようなデータを作成したいと思います。次に、発生するすべてのペアのうち1つだけが列8の最大値を維持する必要があります。たとえば、rs | 860 rs | 756は行6(つまり3269)に最大値があるため、行1と4を削除する必要があります。同様に、rs | 110の場合は、rs | 77 row5を削除する必要があります。次に、列8に同じ値を持つペアがある場合は、列7に高い値を持つペアを維持する必要があります。たとえば、rs | 233 rs | 79 row7の場合、列7の下位値(0.4)を削除する必要があります。すべてのペアについて、列8と列7の間に高い/低い差がない場合は、どちらかを削除できます。
希望の出力 File2
bb yy rs|260 rs|310 xx aa 0.3 9838
bb yy rs|77 rs|110 xx aa 0.5 2291
bb yy rs|756 rs|860 xx aa 0.8 3269
bb yy rs|79 rs|233 xx aa 0.7 1397
答え1
これはエレガントではないawk
ソリューションです。
{
split($3, a, "|")
split($4, b, "|")
if (a[2] > b[2]){
$3=b[1]"|"b[2]
$4=a[1]"|"a[2]
}
split(arr[$3" "$4], c, " ")
if ($8 > c[8]){
arr[$3" "$4] = $0
}
}
END{
for (item in arr){
print(arr[item])
}
}
次に実行
awk -f script.awk input
間隔は維持されず、順序はランダムです。
答え2
確立されたpfnueselの答え、
{
split($3, a, "|")
split($4, b, "|")
if (a[2] > b[2]){
$3=b[1]"|"b[2]
$4=a[1]"|"a[2]
}
key=$3" "$4
split(arr[key], c, " ")
if ($8 > c[8] || ($8 == c[8] && $7 > c[7])){
arr[key] = $0
}
}
END{
for (item in arr){
print(arr[item])
}
}
質問に示すように(明示的に言及されていない)、3番目と4番目の列の値が次の形式であるとします。
some_string|数字
スペースは説明目的でのみ使用され、ひも文字が含まれていません|
。このタグは以下に基づいています。数字s;これひもプレフィックスは比較されません。
のようにpfnueselの答え、使用法は
awk -f script.awk file1
入力ファイルの正確な間隔は失われますが、読み取ることができる列間隔は、パイピングによって(再)生成することができます column -t
。
awk -f script.awk file1 | column -t > file2