4개 열의 탭으로 구분된 파일이 있는데 마지막 열에 중복되는 경우가 있습니다. 다음은 문서에서 발췌한 내용입니다.
chr7 116038644 116039744 GeneA
chr7 116030947 116032047 GeneA
chr7 115846040 115847140 GeneA
chr7 115824610 115825710 GeneA
chr7 115801509 115802609 GeneA
chr7 115994986 115996086 GeneA
chrX 143933024 143934124 GeneB
chrX 143933119 143934219 GeneB
chrY 143933129 143933229 GeneC
열의 각 중복 값 집합에 대해 다음과 같이 변환하고 싶습니다(열의 중복되지 않은 값을 실제로 건드리지 않고).
chr7 116038644 116039744 GeneA-1
chr7 116030947 116032047 GeneA-2
chr7 115846040 115847140 GeneA-3
chr7 115824610 115825710 GeneA-4
chr7 115801509 115802609 GeneA-5
chr7 115994986 115996086 GeneA-6
chrX 143933024 143934124 GeneB-1
chrX 143933119 143934219 GeneB-2
chrY 143933129 143933229 GeneC
또는 Bash awk
루프 를 사용하여 이 작업을 어떻게 수행할 수 있나요 ?sed
for
답변1
이 시도
awk -F'\t' -v OFS='\t' '{$4=$4 "-" (++count[$4])}1' file.tsv
이는 네 번째 필드 값의 각 발생을 카운터 배열 count
(네 번째 필드의 값이 "인덱스"로 사용됨)에 저장하고 해당 카운터의 사전 증가된 값을 네 번째 필드와 대시에 추가합니다.
위의 "간단한" 예에는 한 가지 단점이 있습니다.파일에 한 번만 나타나는 열 4의 값에 명확성 번호를 추가하기도 합니다. 이를 억제하려면 다음과 같은 이중 전달 접근 방식을 사용할 수 있습니다(가독성을 높이기 위해 명령을 두 줄로 분할 \
).
awk -F'\t' -v OFS='\t' 'NR==FNR{f[$4]++}\
NR>FNR{if (f[$4]>1) {$4=$4 "-" (++count[$4])}; print}' file.tsv file.tsv
처리할 파일이 기록되어 있습니다.두 배매개변수로 사용되므로 두 번 읽혀집니다.
- 첫 번째 읽기( 전역
FNR
행 카운터와 동일한 파일별NR
행 카운터로 표시됨)에서는 열 4의 각 고유 값이 파일에 나타나는 빈도를 간단히 계산하고 이를 배열에 저장합니다f
. - 두 번째로 파일을 읽을 때 "간단한" 방법과 같은 실제 텍스트 처리를 수행하고 발생 카운터를 열 4에 추가합니다. 단, 첫 번째 패스에서 발견된 총 발생 횟수가 1보다 큰 경우에만 해당됩니다.
이 접근 방식은 전체 파일의 버퍼링을 방지하므로 파일이 매우 큰 경우 이점이 될 수 있습니다. 물론 파일을 두 번 읽으므로 처리 시간이 길어집니다.
일반적으로 텍스트 처리를 위해 쉘 루프를 사용할 필요는 거의 없습니다. awk
예를 들어 루프 작업이 더 효율적인 방식으로 자체적으로 수행될 수 있기 때문입니다.
답변2
예제에 표시된 대로 입력 파일이 네 번째 열로 그룹화되어 있다고 가정합니다.
$ cat tst.awk
$NF != prev {
prt()
cnt = 0
prev = $NF
}
{ rec[++cnt] = $0 }
END { prt() }
function prt() {
for (i=1; i<=cnt; i++) {
print rec[i] (cnt > 1 ? "-"i : "")
}
}
.
$ awk -f tst.awk file
chr7 116038644 116039744 GeneA-1
chr7 116030947 116032047 GeneA-2
chr7 115846040 115847140 GeneA-3
chr7 115824610 115825710 GeneA-4
chr7 115801509 115802609 GeneA-5
chr7 115994986 115996086 GeneA-6
chrX 143933024 143934124 GeneB-1
chrX 143933119 143934219 GeneB-2
chrY 143933129 143933229 GeneC
답변3
이것은 "-만 추가됩니다.숫자해당 값이 고유하지 않으면 지정된(대상) 필드(예제에서는 네 번째 필드)에 추가됩니다. 또한 입력이 대상 열을 기준으로 정렬되지 않은 경우를 처리하고 입력 열 수에 관계없이 작동합니다.
다음 AWK 스크립트는 대상 필드별로 입력을 정렬해야 하므로 파이프를 사용하여 원래 행의 번호를 매기고 (현재) 다섯 번째 필드(첫 번째 필드가 선행 숫자임)로 정렬하고 비-행에 접미사를 추가합니다. 다섯 번째 필드의 고유 값으로, 행을 원래 순서로 되돌리고 선행 숫자를 제거합니다.
nl file | sort -b -t '<TAB>' -k5,5 -k1n,1n | awk -F '\t' -v OFS='\t' -v kf=5 '
function prn () {
for (i = 1; i <= nfl; i++) {
if (i == kf)
printf("%s", prc[i] ( sw || cnt[prc[i]] ? "-"++cnt[prc[i]] : ""))
else
printf("%s", prc[i])
printf("%s", (i == nfl ? ORS : OFS))
}
}
NR > 1 {
sw = ($kf == prc[kf])
prn()
}
{
nfl = split($0, prc)
}
END {
if (NR > 0)
prn()
} ' | sort -k1n,1n | cut -f 2-
이 AWK 스크립트의 요점은 인쇄하는 것입니다.더 일찍kf
행의 첫 번째 필드가 현재 행의 필드와 같은지 또는 kf
첫 번째 필드가 한 번 이상 발생했는지 확인합니다 . 두 경우 모두, kf
번째 필드는 추가된 횟수와 함께 인쇄됩니다.
명확하게 하려는 열의 실제 위치를 반영하도록 -v kf=5
(및 키) 를 조정해야 합니다 .-k5,5
sort
다음 예(행을 섞고 열을 추가한 예)를 고려하면 다음과 같습니다 file
.
chr7 116038644 116039744 GeneA foo
chrX 143933024 143934124 GeneB foo
chr7 116030947 116032047 GeneA foo
chr7 115824610 115825710 GeneA foo
chrY 143933129 143933229 GeneC foo
chr7 115994986 115996086 GeneA foo
chrX 143933119 143934219 GeneB foo
chr7 115801509 115802609 GeneA foo
chr7 115846040 115847140 GeneA foo
출력은 다음과 같습니다:
chr7 116038644 116039744 GeneA-1 foo
chrX 143933024 143934124 GeneB-1 foo
chr7 116030947 116032047 GeneA-2 foo
chr7 115824610 115825710 GeneA-3 foo
chrY 143933129 143933229 GeneC foo
chr7 115994986 115996086 GeneA-4 foo
chrX 143933119 143934219 GeneB-2 foo
chr7 115801509 115802609 GeneA-5 foo
chr7 115846040 115847140 GeneA-6 foo
답변4
간단한 2단계 awk
명령:
$ awk -F '\t' '
BEGIN { OFS=FS }
pass == 1 { count[$4]++; next }
count[$4] > 1 { $4 = $4 "-" ++number[$4] }; 1' pass=1 file pass=2 file
chr7 116038644 116039744 GeneA-1
chr7 116030947 116032047 GeneA-2
chr7 115846040 115847140 GeneA-3
chr7 115824610 115825710 GeneA-4
chr7 115801509 115802609 GeneA-5
chr7 115994986 115996086 GeneA-6
chrX 143933024 143934124 GeneB-1
chrX 143933119 143934219 GeneB-2
chrY 143933129 143933229 GeneC
이는 입력 파일이 탭으로 구분되어 있다고 가정합니다. -F '\t'
그렇지 않은 경우 수정하거나 삭제하세요.
파일을 처음 탐색할 때 연관 배열은 count
네 번째 열에 있는 각 유전자 이름의 발생 횟수로 채워집니다.
파일을 두 번째로 통과할 때 데이터세트에 유전자 이름이 여러 번 나타나는 경우(파일을 통해 첫 번째 통과 시) 대시와 숫자가 유전자 이름 끝에 추가됩니다.
counter
추가된 숫자는 배열 에서와 마찬가지로 유전자 이름으로 입력되는 또 다른 카운터입니다 .