특정 문자열이 포함된 연속 라인을 찾아 테이블을 기준으로 파일 수정

특정 문자열이 포함된 연속 라인을 찾아 테이블을 기준으로 파일 수정

해결할 수 없는 텍스트 조작 문제가 있습니다. 아래와 같은 텍스트 파일(text.txt)이 있다고 가정해 보겠습니다. 어떤 경우에는 가 있는 줄 /locus_tag다음에 가 있는 줄이 오고 /gene다른 경우에는 그렇지 않습니다. /locus_tag뒤에 a가 없는 모든 줄을 찾은 /gene다음 아래 표(table.txt)를 사용하여 /locus_taga를 일치시키고 .txt 뒤의 텍스트 파일에 /gene추가하고 싶습니다 ./gene/locus_tag

이 작업을 수행하는 방법에 대한 아이디어가 있으면 좋을 것입니다.

/locus_tag="LOCUS_23770"
/note="ABC"
/locus_tag="LOCUS_23780"
/note="DEF"
/locus_tag="LOCUS_23980"
/note="GHI"
/locus_tag="LOCUS_24780"
/gene="BT_4758"
/note="ONP"
/locus_tag="LOCUS_25780"
/gene="BT_4768"
/note="WZX"

테이블

/locus_tag       /gene
LOCUS_00010      BT_4578
LOCUS_00020      BT_4577
LOCUS_00030      BT_2429

답변1

링크 파일을 사용하면 작동합니다.

awk 'BEGIN{FS="[ =]+"; OFS="="}
     BEGINFILE{fno++}
     fno==1{locus["\""$1"\""]="\""$2"\""; }
     fno>1{if (old ~ /LOCUS/ && $0 !~ /gene/) print "/gene", locus[old]; old=$3; print}
    ' table file1

앞으로

                     /locus_tag="LOCUS_00030"
                     /note="WP_011108293.1 hypothetical protein (Bacteroides

뒤쪽에

                     /locus_tag="LOCUS_00030"
/gene="BT_2429"
                     /note="WP_011108293.1 hypothetical protein (Bacteroides

awk연습 에 익숙하지 않기 때문에

awk 'BEGIN{FS="[ =]+"; OFS="="}
# set up the input field separator as any group of spaces and/or =
# and set the output field separator as =

     BEGINFILE{fno++}
     # Whenever you open a file, increment the file counter fno

     fno==1{locus["\""$1"\""]="\""$2"\""; }
     # if this is the first file (i.e. table) load the array `locus[]`
     # but wrap the fields in "..." so that they are exactly like the data file entries

     fno>1{if (old ~ /LOCUS/ && $0 !~ /gene/) print "/gene", locus[old]; old=$3; print}
     # if this is a data file
     # if the current value of old (i.e. the previous line) is a LOCUS
     # and && this line ($0) isn't a gene
     # add a gene by indexing into the locus array based upon the value of old
     # because old contains the last LOCUS we found
     # in all cases
     #    set old to the 3rd field on the current line,
     #       which on any LOCUS line is the string "LOCUS_?????" and
     #    print the current line
     # See note below re $2 vs $3 and FS

    ' table file1
    # your input files, table must be first, you can have more data files if you want

또는 multichar가 없는 경우 multichar 와 달리 데이터 파일의 텍스트 앞 공백에서 중단되지 않도록 FS그대로 두십시오 .old=$2

아래에서는 읽고 있는 파일을 기반으로 필드 구분 기호를 설정하십시오 FS=(fno==1)?" ":"=". 테이블과 =데이터 공간

awk 'BEGIN{OFS="="}
     BEGINFILE{fno++;FS=(fno==1)?" ":"="}
     fno==1{locus["\""$1"\""]="\""$2"\""; }
     fno>1{if (old ~ /LOCUS/ && $0 !~ /gene/) print "/gene", locus[old]; old=$2; print}
    ' table file1

전제는 테이블 파일이 메모리를 차지할 만큼 크지 않다는 것입니다.

빈 유전자에 맞지 않으면 누락된 유전자에 메시지를 삽입하여 테스트합니다./gene=

fno>1{if (old ~ /LOCUS/ && $0 !~ /gene/) print "/gene", (old in locus)?locus[old]:"\"GENE_MISSING_AT_LOCUS\""; old=$3; print}

사용 중인 버전 old과 일치 하도록 필드 참조를 변경하세요.FS

                     /locus_tag="LOCUS_00020"
/gene="GENE_MISSING_AT_LOCUS"
                     /note="WP_008765457.1 hypothetical protein (Bacteroides

편집하다

연결한 예제 파일을 보면 위 예제와 실제 데이터의 형식 차이는 단지 필드 번호와 혼동되는 문제일 뿐입니다. . old=$2로 변경하면 됩니다 old=$3. 위에서 수정했습니다.

관련 정보