awk: 첫 번째 줄의 하위 문자열과 일치하는 탭으로 구분된 열 추출

awk: 첫 번째 줄의 하위 문자열과 일치하는 탭으로 구분된 열 추출

헤더(첫 번째 줄)가 다른 텍스트 파일("strings.txt")에 나열된 특정 문자열과 일치하는 텍스트 파일("columns.txt")에서 탭으로 구분된 열을 추출하고 싶습니다.

"columns.txt"는 다음과 같습니다.

rs2438689   rs54666437   rs9877702046   rs025436779...
0           0            0              1
1           1            2              2 
0           1            2              0 
...         ...          ...            ...

"strings.txt"는 다음과 같습니다:

rs2438689
rs9877702046   
...

출력 텍스트 파일 "output.txt"는 다음과 같아야 합니다(탭으로 구분).

rs2438689   rs9877702046...
0           0              
1           2               
0           2               
...         ...    

awk로 이 작업을 수행하는 방법에 대한 제안이 있습니까? 감사합니다!

답변1

Awk 대신에 쉼표로 구분된 열 이름 목록을 만들고 이를 다음의 s strings.txt목록으로 사용하는 것은 어떻습니까 ?namedcolcsvtool

$ csvtool -t TAB -u TAB namedcol "$(paste -sd, < strings.txt)" columns.txt
rs2438689   rs9877702046
0   0
1   2
0   2
... ...

또는 csvcut/csvformatPython 기반의 경우 와 유사합니다 csvkit.

$ csvcut -tc "$(paste -sd, < strings.txt)" columns.txt | csvformat -T
rs2438689   rs9877702046
0   0
1   2
0   2
... ...

답변2

와 함께perl

$ perl -F'\t' -lane 'if(!$#ARGV){ $h{$_}=1 }
                     else{ @i = grep { $h{$F[$_]} == 1 } 0..$#F if !$c++;
                           print join "\t", @F[@i]}' strings.txt columns.txt
rs2438689   rs9877702046
0   0
1   2
0   2
  • if(!$#ARGV){ $h{$_}=1 }첫 번째 입력 파일의 경우 줄 내용을 키로 사용하여 해시를 만듭니다.
  • @i = grep { $h{$F[$_]} == 1 } 0..$#F if !$c++두 번째 파일의 첫 번째 줄에 대해 해시에서 일치하는 모든 열 이름의 인덱스 목록을 만듭니다.
  • print join "\t", @F[@i]일치하는 열을 인쇄

답변3

수정 중이전 질문에 대한 내 솔루션:

awk -F '\t' -f script.awk strings.txt columns.txt

어디에script.awk

BEGIN { OFS = FS }

FNR == NR {
    columns[$1] = 1
    next
}

FNR == 1 {
    for (i = 1; i <= NF; ++i)
        if ($i in columns)
            keep[i] = 1
}

{
    nf = split($0, fields, FS)
    $0 = ""
    j = 0

    for (i = 1; i <= nf; ++i)
        if (i in keep)
            $(++j) = fields[i]

    print
}

여기서 FNR == NR블록은 명령줄에 나열된 첫 번째 파일( strings.txt)에서 읽는 동안에만 실행됩니다. columns열 이름인 키로 배열을 채웁니다 . 나머지 코드는 다음과 같습니다.다소간현재 열이 (블록에) 유지하려는 열인지 확인하는 양식과는 별도로 이전 솔루션과 변경되지 않았습니다 FNR == 1.


다음과 같은 문제를 해결합니다.댓글에 있는 질문:

항상 처음 6개 열을 복사하고 에서 열 머리글을 자르려면 _다음을 변경하십시오.

FNR == 1 {
    for (i = 1; i <= NF; ++i)
        if ($i in columns)
            keep[i] = 1
}

~ 안으로

FNR == 1 {
    for (i = 1; i <= NF; ++i) {
        sub("_.*", "", $i)
        if (i <= 6 || $i in columns)
            keep[i] = 1
    }
}

답변4

아래 스크립트를 사용하여 완료하면 시간이 오래 걸릴 수 있지만 제대로 작동했습니다.

k=wc -l file1| awk '{print $1}'

for ((i=1;i<=$k;i++));  do for j in `cat file2`; do awk -v i="$i" -v j="$j" '$i == j {x=NR+k}(NR<=x){print $i}' file1; done ; done>final.txt

z=`wc -l final.txt| awk '{print $1}'`

for ((i=1;i<=$z;i++)); do j=$(($i+3)); sed -n ''$i','$j'p' final.txt >file_starting_with_$i.txt; i=$j; done

paste file_starting_with*

산출

rs2438689   rs9877702046
0       0
1       2
0       2

관련 정보