문자열의 입력 파일을 읽고 일치 항목을 내부에서 일치시키고 변경하는 방법은 무엇입니까?

문자열의 입력 파일을 읽고 일치 항목을 내부에서 일치시키고 변경하는 방법은 무엇입니까?

별도의 줄에 문자열/파일 이름이 포함된 텍스트 파일이 있습니다. filename.txt. 수백 개의 파일 이름이 있습니다

ABC123_S386_R1_001
JKL345_S441_R1_001
filename9000_S587_R1_001

문자열/파일 이름과 추가 데이터가 포함된 또 다른 텍스트 파일입니다. results.txt:

>ABC123_S386_R1_001 
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
>JKL345_S441_R1_001
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
>abc7890_S387_R1_001  
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
>filename9000_S587_R1_001
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN

이제 의 모든 파일 이름이 filename.txt에 존재하지 않으며 results.txt순서대로 표시되지도 않습니다. filename.txt의 모든 파일 이름에는 접두사를 삽입하고 다른 파일 이름에는 삽입하고 싶지 results.txt않습니다.

문자열 입력 파일을 읽고, 다른 파일과 일치시키고, 일치 항목을 변경하려면 어떻게 해야 합니까?

이전에는 개별 파일 이름을 와 일치시키고 sequence.txt줄 번호를 얻은 다음 sed줄 번호와 함께 사용하여 한 줄이나 줄 블록을 변경했습니다.

내가 원하는 출력은 다음과 같습니다

>h-19/US/CA-ABC123_S386_R1_001 
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
>h-19/US/CA-JKL345_S441_R1_001
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
>abc7890_S387_R1_001  
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
>h-19/US/CA-filename9000_S587_R1_001
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN

h-19/US/CA-모든 일치 항목에 추가하고 싶은 접미사는 어디에 있습니까?

편집: >변경해야 하는 모든 문자열의 첫 번째 문자입니다. >파일 이름 뒤에 오는 공백도 앞에 문자가 없습니다.

답변1

의 관련 줄에 results.txt파일 이름 뒤에 공백이 포함되어 있지 않다고 가정하면 다음 awk프로그램이 작동합니다.

awk -v prefix="h-19/US/CA-" 'NR==FNR{fnames[$1]; next} \
    /^>/{name=substr($0,2); if (name in fnames) {sub(/^>/, ">" prefix)} }1' filenames.txt results.txt
  • 먼저 구문 분석 filenames.txt한 다음 results.txt.
  • 구문 분석하는 동안 filenames.txt( FNR파일별 라인 카운터는 NR전역 라인 카운터와 동일함) 모든 파일 이름(라인의 유일한 필드)을 배열에 등록 fnames하지만 실행을 즉시 다음 라인으로 건너뜁니다.
  • 구문 분석하는 동안 results.txt줄이 로 시작하는지 확인합니다 >. 그렇다면 해당 문자 뒤의 하위 문자열( 임시로 저장됨 name)이 의 "배열 인덱스"에서 발견되는지 확인합니다 fnames. 이 경우 sub()선행을 +접두사 >로 대체하고 (지시문을 통해 ) 변수로 전달하는 데 사용됩니다 .>awkprefix-v
  • 겉으로 보기에는 "길어"인 것처럼 보이는 것은 가능한 모든 수정 사항을 포함하여 현재 줄을 인쇄하도록 1지시합니다 (그러나 첫 번째 파일을 처리하는 동안 해당 부분에 도달하지 못하는 경우에만 해당됩니다).awkresults.txt

그 자체로 는 awk파일을 내부에서 수정할 수 없으므로 임시 파일을 사용하여 작업해야 합니다. 그러나 충분히 새로운 버전의 GNU Awk(> 4.1.0)가 있는 경우 inplace확장 기능을 사용할 수 있습니다. 물론 그런 다음 해당 파일에 대한 옵션을 꺼야 합니다 filenames.txt.

awk -i inplace -v prefix=" ... " ' ... ' inplace=0 filenames.txt inplace=1 results.txt

그러면 에 대한 내부 편집이 꺼졌다 filenames.txt가 다시 켜집니다 results.txt.

답변2

sed보류 공간에서 파일 이름을 수집한 다음 일치 항목을 확인하는 모든 줄에 대해 변경할 results.txt줄을 필터링할 수 있습니다.

sed -e '1,/^$/{H;1h;d;}' -e 'G;/^>\(.*\).*\n\1\n/s_^>_>h-19/US/CA-_;P;d' filename.txt <((echo)) results.txt
  • <((echo))파일 사이 에 빈 줄을 전달하여 1,/^$/첫 번째 파일의 모든 줄(및 빈 줄)을 처리합니다.
  • 해당 줄은 공간을 유지하기 위해 추가된 다음 삭제됩니다 H;1h;d( 1h개행으로 보류 공간을 시작하지 않음).
  • G의 모든 라인에 보류 공간을 추가하고 result.txt파일 이름인 문자열 /^>\(.*\).*\n\1\n/로 시작하는 라인과 일치합니다 (보류 공간에서 개행 문자로 묶음).>
  • s_^>_>h-19/US/CA-_해당 라인을 교체합니까?
  • P;d추가된 정크 없이 첫 번째 줄만 인쇄합니다. s/\n.*//대신 할 수 있습니다

답변3

perl입력 파일에 대한 내부 편집에 사용 :

pfx='h-19/US/CA-' \
perl -pi -e '
  BEGIN { %h = map { tr/\n//dr => $ENV{pfx}} <STDIN>}
  s/^>\K(?=(.*))/$h{$1}/;
' results.txt < filename.txt

관련 정보