컬럼에 특정 문자가 존재하는 경우 특정 컬럼의 내용을 분할합니다.

컬럼에 특정 문자가 존재하는 경우 특정 컬럼의 내용을 분할합니다.

이 데이터 탭이 구분되어 있습니다.

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

이 명령은 세 가지 간단한 단계를 수행합니다.

  1. s/NA/&\tNA/g- 모두 탭으로 구분된 NAdouble 로 바꿉니다 NA.
  2. s/(/\t/g- 왼쪽 대괄호를 모두 탭 문자로 바꿉니다.
  3. 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

관련 정보