입력 목록을 기반으로 파일의 텍스트를 일괄 변경하는 방법

입력 목록을 기반으로 파일의 텍스트를 일괄 변경하는 방법

아래와 같이 엄청난 양의 데이터가 있습니다.

파일 1(4600줄)

Genome  Gene    Boolean
E15-12  VFG000923   1
E15-13  VFG000924   1
E15-14  VFG000926   1
E15-15  VFG000928   1
E15-16  VFG000930   1
E15-17  VFG000932   1
E15-18  VFG000933   0
E15-19  VFG001448   0
E15-24  VFG013465   1

col2의 정보를 다음과 같이 분류하고 싶습니다.

파일 2(180줄)

VFG000923|fepA
VFG000924|fepB
VFG000926|fepD
VFG000928|fepG
VFG000930|entF
VFG000932|entE
VFG000933|entB
VFG001448|kpsD
VFG001450|kpsM
VFG044165|entS

나가

Genome   Gene         Boolean
E15-12  VFG000923|fepA  1
E15-13  VFG000924|fepB  1
E15-14  VFG000926|fepD  1
E15-15  VFG000928|fepG  1
E15-16  VFG000930|entF  1
E15-17  VFG000932|entE  1
E15-18  VFG000933|entB  0
E15-19  VFG001448|kpsD  0
E15-20  VFG001450|kpsM  1

@val0x00ff의 코드 사용(댓글 참조)

Genome  Gene    Boolean

E15-14 VFG000923|fepA 1

E15-14 VFG000924|fepB 0

E15-14 VFG000926|fepD 1

E15-14 VFG000928|fepG 0

sed나 awk를 사용하여 이를 수행할 수 있는 방법이 있습니까?

답변1

그리고 sed:

sed '/|/{H;d;};G;s/\([A-Z0-9]*\)\(.*\n\)\1\(|[^[:cntrl:]]*\)/\1\3\2\1\3/;P;d' FILE2 FILE1

그러면 문제가 해결될 것입니다. 이건 적응이야이 답변. 자세한 설명이 나와있습니다.

답변2

이것은 작동합니다:

$ awk 'NR==FNR{k=sub(/\|.*/,$1); a[k]=$1; next} ($2 in a){$2=a[$2]}1' file2 file
Genome Gene Boolean
E15_14 VFG000923|fepA 1
E15_14 VFG000924|fepB 1
E15_14 VFG000926|fepD 0
E15_14 VFG000928|fepG 1
E15_14 VFG000930|entF 0
E15_14 VFG000932|entE 0
E15_14 VFG000933|entB 1
E15_14 VFG001448|kpsD 1
E15_14 VFG001450|kpsM 1
E15_14 VFG044165|entS 0

또는 읽기가 더 쉽습니다.

awk 'NR==FNR{
        k=sub(/\|.*/,$1); 
        a[k]=$1; 
        next
    } 
    ($2 in a){
        $2=a[$2]
    }1' file2 file

설명하다

  • NR==FNR{ }: NR은 현재 입력 라인 번호이고, FNR은 현재 파일의 라인 번호입니다. 여러 파일을 읽을 때 두 파일은 첫 번째 파일을 읽을 때만 동일합니다.
  • k=sub(/\|.*/,$1);:줄에서 다음 부분을 제거합니다 |(위에서 언급한 것처럼 이는 첫 번째 파일에서만 발생하므로 NR==FNR).
  • a[k]=$1;: 첫 번째 파일의 첫 번째 필드를 키가 유전자 이름인 배열의 값으로 저장합니다 ( a첫 번째 필드 |이후의 모든 항목은 제거됨).
  • next: 다음 줄로 이동합니다. 이렇게 하면 첫 번째 파일을 읽는 동안 다음 블록을 실행하지 않게 됩니다.
  • ($2 in a): 두 번째 필드가 배열의 키로 존재하는 경우 a(두 번째 파일에 대해서만 실행됩니다)
  • $2=a[$2]: 두 번째 필드를 afor 에 저장된 항목 으로 설정합니다 $2.
  • 1: 이것은 "현재 줄 인쇄"에 대한 awk의 약어입니다. awk의 내용이 true로 평가되면 기본 작업은 현재 줄을 인쇄하는 것이기 때문에 작동합니다. 항상 true 이므로 1인쇄됩니다.

답변3

perl -lne '
   @ARGV and %h=(%h, /(.*)\|/ => $_),next;
   !@ARGV and !$a++ and print,next;
   print s//$h{$1}/r if exists $h{(/\h\K(\S+)(?=\h)/)[0]};
' FILE2 FILE1

설명하다

  • 더 작은 파일(FILE2)을 읽을 때 이전 데이터의 해시를 채우고 %h값은 전체 라인입니다.keyed|
  • 더 큰 파일(FILE1)을 읽을 때 먼저 다음을 사용하여 첫 번째 줄을 인쇄합니다. !@ARGV and !$a++의미가 지워졌고 @ARGV처음으로 변수를 볼 수 있습니다.$a
  • 나머지 행에서는 식별된 두 번째 필드를 통해 regex /\h\S+\h/키가 해시에 존재하는지 확인합니다 %h. 이것이 사실인 것으로 확인되면 필드를 해당 키에 해당하는 값으로 바꿉니다.

관련 정보