awk를 사용하여 같은 줄에 여러 일치 항목을 인쇄하는 방법

awk를 사용하여 같은 줄에 여러 일치 항목을 인쇄하는 방법

안녕하세요. 테이블 파일이 있습니다(구분 기호 = \t) A.txt.

205 toto patho
207 tata benign
208 titi likely_patho

그리고 B.txt:

210 lolo patho
211 lala benign
212 lili benign

세 번째 열이 "patho" 또는 "likely_patho"인 경우 두 번째 열의 값을 인쇄하는 파일이 필요합니다. 이 예를 통해 다음을 얻을 수 있습니다.

A toto;titi
B lolo

이를 위해 나는 다음을 수행했습니다.

for bla in *.txt; do
r="$(basename -s ".txt" $bla)"
awk -v filename=$r '($3=="patho" || $3=="likely_patho") {print filename"\t"$2}' $bla >> result.txt ;
done

그러나 파일에 여러 일치 항목(예 A.txt: )이 포함된 경우 이 코드는 각 일치 항목에 대해 한 줄을 제공합니다.

A toto
A titi
B lolo

어떻게 하면 올바른 출력을 얻을 수 있나요? 감사해요

답변1

awk를 사용하십시오.

$ cat tst.awk
BEGIN {
    split(t,tmp)
    for ( i in tmp ) {
        tgts[tmp[i]]
    }
    FS = OFS = "\t"
}
FNR == 1 {
    fname = FILENAME
    sub(/\.[^.]*$/,"",fname)
}
$3 in tgts {
    hits[fname] = (fname in hits ? hits[fname] ";" : "") $2
}
END {
    for ( fname in hits ) {
        print fname, hits[fname]
    }
}

$ awk -v t='patho likely_patho' -f tst.awk *.txt
A       toto;titi
B       lolo

답변2

노력하다:

awk '  FNR==1 {  f=FILENAME;
                 sub(/\.[^.]*$/,"",f);
                 printf "%s%s\t",aline,f;
                 aline="\n";
                 s=""
       }
       ($3=="patho" || $3=="likely_patho"){
                 printf "%s%s",s,$2;
                 s="; "
       }
       END{print ""}
    ' ./*.txt

답변3

시도해 보세요(한 줄이면 됩니다).

awk -v filename="$r" 'BEGIN { string=filename "\t" }
          ($3=="patho" || $3=="likely_patho") {printf string $2; string=";" }
          END { printf "\n" } ' $bla >> result.txt ;

나는 string접두사로 사용하고 파일 이름을 먼저 인쇄한 다음 세미콜론을 인쇄합니다.

마지막 개행 문자를 추가해야 합니다.

답변4

Perl 사용(가독성을 위해 추가 줄바꿈 사용):

$ perl -MFile::Basename -F'\t' -le '
$f = fileparse($ARGV, qw(.txt)) if $. == 1;
if ($F[2] =~ /^(likely_)?patho$/) {
  push @{ $files{$f} }, $F[1]
};
close(ARGV) if eof;   # close each input file and reset the line counter $. at eof

END {
  foreach (sort keys %files) {
    print "$_\t", join(";",@{ $files{$_} })
  }
}' A.txt B.txt
A       toto;titi
B       lolo
  • -MFile::BasenamePerl에게 로드하라고 지시파일::기본 이름기준 치수. 이것은 Perl에 포함된 핵심 Perl 모듈입니다.

  • -F필드 구분 기호(탭)를 설정하고 Perl의 -a자동 분할 모드(각 입력 행을 awk와 유사하게 명명된 배열로 분할 @F)와 -n입력을 반복하는 Perl의 옵션( sed -n및 처럼 작동 awk)도 활성화합니다.

  • -l줄 끝 자동 처리를 활성화합니다( \n기본값). 즉, 각 입력 줄의 끝에서 개행 문자를 제거하고(Perl의 chomp()함수를 사용하여) 이를 각 명령문의 끝에 추가합니다 print.

  • 모든 Perl 명령줄 옵션은 에 설명되어 있습니다 man perlrun.

스크립트는 각 입력 줄을 반복하고 세 번째 필드에서 일치하는 항목을 찾을 때마다( $F[2]-perl 배열 인덱스는 0에서 시작) 두 번째 필드를 (HoA) middle 이라는 배열 해시에 추가합니다 %files. 이는 키가 기본 파일 이름이고 값이 두 번째 필드의 문자열 배열인 해시(연관 배열)입니다. Perl 데이터 구조에 대한 자세한 내용은 perldata, 및 perllol의 매뉴얼 페이지를 참조하십시오.perldsc

모든 입력을 읽고 처리한 후에는 요청된 형식으로 파일 이름별로 정렬된 데이터를 출력합니다.


참고: ... if $. == 1;close(ARGV) if eof줄과 함께 각 새 파일의 첫 번째 줄에서 기본 파일 이름만 추출되는지 확인하십시오. 이것은 필수는 아니며 매우 큰 입력 파일이 있는 경우에만 유용할 작은 최적화입니다. 약간 더 짧은 행을 선호하거나 성능이 문제가 되지 않는 경우 close(ARGV) ...행과 if $. == 1조건을 제거하세요.

관련 정보