해당 행이 없는 행 집합을 인쇄합니다.

해당 행이 없는 행 집합을 인쇄합니다.

해당 쌍 없이 두 줄 세트를 인쇄하려고 합니다. 결국 이 줄을 삭제하고 싶습니다.

예:

NM00123_rn5_0_1_2
XXXXXXXXXXXXXXXXXXXXXXXXXXX
NM00123_mm10_0_1_2
XXXXXXXXXXXXXXXXXXXXXXXXXXXX
NM00124_rn5_0_1_3
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
NM00124_mm10_0_1_3
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
NM00125_rn5_0_1_4
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
NM00126_rn5_0_1_5
RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRr
NM00126_mm10_0_1_5
RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR

NM으로 시작하는 줄이 제목이고, 다음 줄은 일련의 문자로 구성됩니다. 쌍의 헤더 행은 rn5 및 mm10을 제외한 모든 위치에서 일치합니다. 나는 rn5 및 mm10 일치 전후의 NM 헤더 번호인 4개 행 세트를 유지하고 싶습니다. 따라서 위의 예에서 rn5의 1행 헤더는 mm10의 3행 헤더와 일치하므로 유지됩니다. 그러나 9행의 rn5 헤더는 해당 쌍이 아니므로 다음을 사용하여 헤더를 인쇄합니다. 그리고 다음 줄 순서. 나는 궁극적으로 동일한 수의 rn5 및 mm10 항목을 포함하는 파일을 갖고 싶습니다.

저는 Unix를 처음 사용하는데, 여러분의 도움에 진심으로 감사드립니다. 감사해요.

예상되는 결과:

위 항목 중 해당 행이 없습니다. 이 경우:

NM00125_rn5_0_1_4
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

답변1

이것은 awk의 다소 복잡한 버전입니다. Steeldriver의 sed 버전과의 몇 가지 차이점은 다음과 같습니다.

  1. mm10기록이 기록되는 순서에 대해 rn5어떠한 가정도 하지 않습니다.
  2. rn5누락된 레코드를 처리할 수 있습니다.
  3. 일치하지 않는 레코드를 stderr.
  4. 추가 코드는 다음과 같습니다 :-)

다음을 통해 실행할 수 있습니다.

awk -f my_program.awk infile

암호:

# find and store a header
/^NM.*/ { header = $0; next }

# we found an mm10 line
header ~ /_rn5/ {

    # get the mm10 line that matches this rn5
    mm_match = header
    sub("_rn5", "_mm10", mm_match)

    # if we have a previous mm10, then print the pair
    if (mm_match in headers) {
        print header
        print
        print mm_match
        print headers[mm_match]

        delete headers[mm_match]
    } else {
        headers[header] = $0
    }
    next
}

# we found an mm10 line
header ~ /_mm10/ {

    # get the rn5 line that matches this mm10
    mm_match = header
    sub("_mm10", "_rn5", mm_match)

    # if we have a previous rn5, then print the pair
    if (mm_match in headers) {
        print mm_match
        print headers[mm_match]
        print header
        print

        delete headers[mm_match]
    } else {
        headers[header] = $0
    }
    next
}

또한 이 코드를 파일 끝에 추가하여 일치하지 않는 줄을 다음으로 출력할 수 있습니다 standard error.

# The END block is here just to output anything that was unmatched
END {
    # dump the unmatched to stderr
    for (header in headers) {
        print header > "/dev/stderr"
        print headers[header] > "/dev/stderr"
    }
}

다음을 통해 실행할 수 있습니다.

awk -f my_program.awk infile > outfile 2> unmatched

outfile요청된 출력(표준 출력을 통해)을 에 출력 하고 나머지 입력(표준 오류를 통해)을 에 출력합니다 unmatched. 다양한 I/O 리디렉션에 대한 자세한 내용은 다음 장을 참조하세요.리디렉션Bash 참조 매뉴얼에 있습니다.

답변2

생각하다요청하신 내용은

  • 4줄 버퍼를 유지하고
  • 다음 내용 rn5(다음 개행까지)이 뒤따르는 내용 mm10(다음 개행까지)과 일치하면 인쇄하고 다시 시작하세요.

이는 추악한 접근 방식일 수 있지만 GNU 용어로 설명하면 다음과 같습니다 sed.

$ sed -n -e :a \
         -e '$!N; /rn5_\(.*\)\n.*\n.*mm10_\1\n/ {p;b}' \
         -e '/.*\n.*\n.*\n/ D' \
         -e ba infile > outfile

$ diff outfile infile
8a9,10
> NM00125_rn5_0_1_4
> zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

관련 정보