AWK for 루프를 입력으로 사용하여 찾기 및 바꾸기

AWK for 루프를 입력으로 사용하여 찾기 및 바꾸기

두 개의 파일이 있습니다.

Ref.txt에는 다음이 포함됩니다.

ABCDEFG,15147,ABC,ABCD,ABCDE
HIJKLMN,500,HIJKLM,HIJKL,HIJK

및 다음을 포함하는 Seq.txt

ABCDEFG
ABCXXXX
ABCDXXX
ABCDEXX
HIJKXXX
HIJKLXX
HIJKLMX
HIJKLMN

Ref.txt 파일의 각 줄의 3-end 필드에 대해 Seq.txt 파일을 검색하고 문자열이 있는 줄을 해당 줄의 첫 번째 필드에 있는 문자열로 바꾸고 싶습니다. 이 예에서 내가 찾고 있는 출력은 다음과 같습니다.

ABCDEFG
ABCDEFG
ABCDEFG
ABCDEFG
HIJKLMN
HIJKLMN
HIJKLMN
HIJKLMN

이것은 잘못된 코드이지만 다음과 같은 명령을 생각하고 있습니다.

awk '{for(i=3; i<=NF; i++) gsub( $i , $1)}

그러나 for 루프는 Ref.txt 파일을 참조하고 gsub 명령은 Seq.txt 파일에서 실행됩니다.

답변1

|이를 수행하는 것을 고려할 수 있는 한 가지 방법은 Ref.txt의 각 줄의 세 번째 끝 필드에서 정규식을 연결하고 값으로 키가 지정된 연관 배열에 저장하여 단일 정규식을 작성하는 것입니다 $1.

그런 다음 각 Seq.txt의 키를 반복할 수 있습니다 $1.

awk -F, '
  NR==FNR {
    # construct a single ERE as $3|$4|$5|etc. keyed on $1
    for(i=3;i<=NF;i++) r[$1] = r[$1] == "" ? $i : r[$1] "|" $i;
    next
  } 
  {
    # test $1 against each ERE and substitute the first matching key
    for(k in r) {
      if ($1 ~ r[k]) {
        $1 = k; 
        break
      }
    }
  }
  1
' Ref.txt Seq.txt

답변2

sed다음과 같은 구성을 사용하여 Posix이를 달성 할 수 있습니다 .

$ sed -ne '
   /,/!G
   y/\n_/_\n/
   s/^\([^_][^_]*\).*__\(.*_\)\{0,1\}\([^,]*\),[^,]*,[^_]*,\1,.*/\3/p
   s/^[^_]*__//;s/$/,/
   y/_\n/\n_/
   /\n/!H
' Ref.txt Seq.txt

참고: 이는 bash여기에 지정된 매개변수의 순서와 개수를 사용하여 명령줄에서 실행됩니다.

Perl정규식을 사용하지 않고도 여기에서 사용할 수도 있습니다.

$ perl -F, -lane '
   if ( @ARGV ) {
     $h{$_} = $F[0] for @F[2..$#F];
     next;
   }
   my $seq = $_;
   my($k) = grep { ! index($seq, $_) } keys %h;
   print $h{$k};
' Ref.txt Seq.txt

답변3

나처럼 게으른 사람이라면 배열과 루프를 처리하고 이를 도구에 맡기고 싶지 않을 것입니다. 이것이 바로 내가 sedRef.txt줄(쉼표로 식별)을 예약된 공간에 두는 것을 선호하는 이유입니다 H. 실제로 패턴이 항상 두 개의 쉼표 사이에 있다는 것을 알기 위해 또 다른 쉼표를 추가했습니다. 그래서 그것은 합산됩니다 /,/{s/$/,/;H;d;}.

이제 의 각 줄에 대해 Seq.txt참조 힙을 예약된 공간에 추가하고 명령이 패턴을 힙에서 찾은 패턴으로 바꾸도록 G합니다 . s정규식은 일반적으로 읽는 것보다 작성하는 것이 더 쉽습니다.

이제 패턴 공간을 살펴보겠습니다.

ABCDEFG\n\nABCDEFG,15147,ABC,ABCD,ABCDE\nHIJKLMN,500,HIJKLM,HIJKL,HIJK
\_____/    \_____/       \_/
replace    by this  if  match
  • 교체할 부품은 처음( ^)에 위치하고, 일치하는 부품( [A-Z]+)과 전후의 일부 부품( [A-Z]*) 이 있습니다.
  • 교체는 개행 문자와 쉼표 사이의 순서입니다.\n[A-Z]*,
  • 일치 항목은 첫 번째 부분에서 역참조된 두 개의 쉼표 사이의 패턴입니다.,\1,

전체적으로 이것은 다음과 같습니다.

sed -E '/,/{s/$/,/;H;d;};G;s/^[A-Z]*([A-Z]{1,})[A-Z]*\n.*\n([A-Z]*),[A-Z0-9,]*,\1,.*/\2/;P;d' Ref.txt Seq.txt

관련 정보