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와 같은 데이터를 만들고 싶습니다. 다음으로, 발생하는 모든 쌍 중에서 하나만 열 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])
}
}
질문에 표시된 것처럼(명시적으로 언급되지는 않음) 세 번째 및 네 번째 열의 값이 다음과 같은 형식이라고 가정합니다.
some_string|숫자
공간은 설명 목적으로만 사용되며,끈문자가 포함되어 있지 않습니다 |
. 이 태그는 다음을 기반으로 합니다.숫자s;이것끈접두사는 비교되지 않습니다.
에서와 같이pfnuesel의 답변, 사용법은
awk -f script.awk file1
입력 파일의 정확한 간격은 손실되지만 읽을 수 있는 열 간격은 파이핑을 통해 (재)생성될 수 있습니다 column -t
.
awk -f script.awk file1 | column -t > file2