이 데이터 탭이 구분되어 있습니다.
ed00011 89 0.12 NA NA No
ed0002s 28 0.11 c3(3.1e-1) NA No
ed0001 22 0.37 NA 186_CR_NCR8_Ot(1.5e-6) No
ed0002a 596 0.89 c301(9.5e-2) 17_CY7_Ot(0.03) Yes
"(...)"가 있는 경우 이를 기준으로 열 4와 5를 분할하고 싶습니다. 존재하지 않는 경우에는 NA만 있습니다. 예를 들어:
ed00011 89 0.12 NA NA NA NA No
ed0002s 28 0.11 c3 3.1e-1 NA NA No
ed0001 22 0.37 NA NA 186_CR_NCR8_Ot 1.5e-6 No
ed0002a 596 0.89 c301 9.5e-2 17_CY7_Ot 0.03 Yes
여기에 제안된 명령을 사용해 보았습니다.awk를 사용하여 열 분할 그러나 "(...)"가 없으면 열이 엉망이 됩니다. 어떤 제안이 있으십니까?
답변1
awk 'BEGIN { OFS="\t"; }
{
if (match($4, /\(.*\)/) > 0) {
$4=substr($4, 1, RSTART - 1)"\t"substr($4, RSTART + 1, RLENGTH - 2)
} else {
$4=$4"\tNA"
}
if (match($5, /\(.*\)/) > 0) {
$5=substr($5, 1, RSTART - 1)"\t"substr($5, RSTART + 1, RLENGTH - 2)
} else {
$5=$5"\tNA"
}
print
}' input > output
여기서 기본 구조는 필드 4 또는 필드 5에 각 줄에 일치하는 대괄호 쌍이 포함되어 있는지 확인하는 것입니다. 그렇다면 필드를 탭으로 구분된 두 개의 값, 즉 대괄호 앞 부분과 대괄호 내부 부분으로 바꾸십시오. RSTART 값은 여는 괄호가 들어가는 위치이고 RLENGTH 값은 닫는 괄호를 포함하므로 길이가 약간 조정되는 것을 볼 수 있습니다. 필드에 괄호가 없으면 탭 문자와 "NA"가 추가됩니다.
열이 다시 계산되면 새 행이 인쇄됩니다.
답변2
BEGIN {
OFS = FS = "\t"
}
{
# Shift some fields to the right to make space for new fields after
# field 4 and 5.
$8 = $6
$6 = $5
# Try matching "(...)" in $4
if (match($4, "[(][^)]+[)]")) {
# Succeeded, make $5 the bit inside the parenthesis
$5 = substr($4, RSTART+1, RLENGTH-2)
# ... and $4 the bit before the parenthesis.
$4 = substr($4, 1, RSTART-1)
} else
$5 = "NA"
# Repeat for $6
if (match($6, "[(][^)]+[)]")) {
$7 = substr($6, RSTART+1, RLENGTH-2)
$6 = substr($6, 1, RSTART-1)
} else
$7 = "NA"
print
}
시험:
$ awk -f script.awk file
ed00011 89 0.12 NA NA NA NA No
ed0002s 28 0.11 c3 3.1e-1 NA NA No
ed0001 22 0.37 NA NA 186_CR_NCR8_Ot 1.5e-6 No
ed0002a 596 0.89 c301 9.5e-2 17_CY7_Ot 0.03 Yes
필드는 출력에서 탭으로 구분되지만 조금 이상해 보입니다. 전달하면 더 잘 작동 column -t
하지만 실제 탭은 손실됩니다.
$ awk -f script.awk file | column -t
ed00011 89 0.12 NA NA NA NA No
ed0002s 28 0.11 c3 3.1e-1 NA NA No
ed0001 22 0.37 NA NA 186_CR_NCR8_Ot 1.5e-6 No
ed0002a 596 0.89 c301 9.5e-2 17_CY7_Ot 0.03 Yes
답변3
신뢰할 수 있는 방법
gawk '{
for(i = 4; i < 6; i++) {
if($i ~ /\(/) {
split($i, arr, "[()]")
$i = arr[1] "\t" arr[2]
} else {
$i = $i"\tNA"
}
}
print
}' OFS='\t' input.txt
신뢰할 수는 없지만 샘플, 방법을 연구 중입니다.
sed 's/NA/&\tNA/g; s/(/\t/g; s/)//g' input.txt
이 명령은 세 가지 간단한 단계를 수행합니다.
s/NA/&\tNA/g
- 모두 탭으로 구분된NA
double 로 바꿉니다NA
.s/(/\t/g
- 왼쪽 대괄호를 모두 탭 문자로 바꿉니다.s/)//g
- 모든 닫는 괄호를 제거합니다.
많은 가정을 하기 때문에 신뢰할 수 없습니다. 대괄호는 열 4와 5에만 나타날 수 있고, NA
문자열은 열 4와 5에만 나타날 수 있으며, 열 4와 5의 숫자 문자열은 항상 c3(3.1e-1)
유사한 형식을 갖습니다. 따라서 이 명령은 c3
괄호로 묶이지 않은 고유한 부품 만 있는 경우 sed
작동하지 않습니다 .
그러나 데이터가 샘플과 완전히 동일하다면 작업이 완료됩니다.
산출
ed00011 89 0.12 NA NA NA NA No
ed0002s 28 0.11 c3 3.1e-1 NA NA No
ed0001 22 0.37 NA NA 186_CR_NCR8_Ot 1.5e-6 No
ed0002a 596 0.89 c301 9.5e-2 17_CY7_Ot 0.03 Yes