다음과 같은 목록이 있습니다.
$$<002L_tbfl
Putative transcription factor 001R;
GO:0006355
GO:0046782
GO:0006351
IPR007031
$$<002L_FRG3G
Uncharacterized protein 002L;
GO:0033644
GO:0016021
IPR004251
나는 각각이 새로운 줄을 시작하고 다시 나타날 $$<
때까지 같은 줄(탭으로 구분)에 다음 항목을 갖기를 원합니다. $$<
이와 같이:
$$<002L_tbfl Putative transcription factor 001R; GO:0006355 GO:0046782 GO:0006351 IPR007031
$$<002L_FRG3G Uncharacterized protein 002L; GO:0033644 GO:0016021 IPR004251
지금까지 나의 접근 방식은 다음과 같습니다.
tr '\n' '\t' < stage1 > stage2
sed 's/$$</\n/g' stage2 > stage3
문제는 위의 방법이 작은 파일에서는 완벽하게 작동하지만 4GB 파일에서는 작동하는 것처럼 보인 다음 짧은 시간 동안 오류나 메시지 없이 빈 파일을 반환한다는 것입니다.
나도 시도해 보았지만 tr '$$<' '\n'
작동하지 않습니다. 이상한 파일이 생성됩니다.
답변1
수행 방법은 다음과 같습니다 sed
.
sed -n '/$$</! H; /$$</{x; s/\n/\t/gp}; ${x; s/\n/\t/gp}' stage1 > stage3
부분으로 나누어져 있습니다:
sed -n
기본 출력(즉, 처리된 입력)이 인쇄되지 않고p
명령을 받은 경우에만 인쇄됨을 의미합니다./$$</! H
선이 보일 때를 의미합니다.아니요포함되어 있으면$$<
"에 추가하세요.시간이전 공간"(예: 준비 영역). 이는!
일반적인 논리를 뒤집어 "이 조건을 충족하지 않는 행에 대해 이 작업을 수행"을 의미합니다.$$<
행 중간에서 발생하는 일을 무시해야 하는 경우 이 설정을 변경합니다(및 ( 예를 들어 줄 앞에 개행을 삽입하는 등 줄 중간을 다르게 처리/^$$</
해야 하는 경우 이를 기록하도록 질문을 편집하세요. )$$<
예약된 공간(예약된 공간)에 이미 콘텐츠가 있는 경우 예약된 공간에 줄을 추가하는 경우
sed
그 사이에 줄바꿈 문자를 삽입하면 예약된 공간에 다음과 같은 텍스트가 작성됩니다.$$<002L_tbfl newline추정 전사 인자 001R newline이동: 0006355…
공간을 "패턴 공간"(일반 작업 라인 버퍼)으로 예약 일반적으로 말하면끝에는 명시적인 개행 문자가 없습니다(암시적입니다). 물론, 공백 내에 명시적으로 개행 문자를 삽입할 수 있습니다.
/$$</{…}
중괄호로 묶인 명령이 포함된 행에서 실행됨을 나타냅니다$$<
.x
e를 의미한다엑스예약된 공간과 패턴 공간의 내용을 변경합니다.s/\n/\t/gp
의미 - 글쎄요, 당연한 거죠, 그렇죠? — 이는 (패턴 공간에서) 개행 문자를 탭으로 바꾸는 것을 의미합니다. G전 세계적으로 그리고피결과를 인쇄합니다.
이 명령이 입력의 첫 번째 라인( 포함
$$<
) 을 읽으면x
해당 라인($$<002L_tbfl
)을 패턴 공간에서 예약된 공간으로 이동하고 예약된 공간의 이전 내용을 패턴 공간으로 이동합니다. 그러나 예약된 공간의 초기 내용은 아무것도 없기 때문에 명령이 적용되지 않습니다s
. 나중에 (예를 들어 7번째 줄에서) 볼 때$$<
(위에 표시된 대로) 새 줄이 포함된 텍스트를 패턴 공간으로 가져오고 (위와 같이) 모든 줄 바꿈을 탭으로 바꾸고 결과를 인쇄합니다.${…}
입력 끝에 도달하면 중괄호로 묶인 명령이 실행됨을 나타냅니다. 이는$$<
예약된 공간에서 마지막 행(즉, 마지막 행)을 지우기 위해 를 볼 때 실행한 것과 동일한 명령입니다 .
경고: POSIX에서의 작동이 보장되지는 않습니다 sed
. 나는 그것을 GNU에서 테스트했습니다 sed
.
답변2
$ cat ip.txt
$$<002L_tbfl
Putative transcription factor 001R;
GO:0006355
GO:0046782
GO:0006351
IPR007031
$$<002L_FRG3G
Uncharacterized protein 002L;
GO:0033644
GO:0016021
IPR004251
$ perl -ne 'chomp if !eof; if($. > 1){print /\$\$</ ? "\n" : "\t"} print' ip.txt
$$<002L_tbfl Putative transcription factor 001R; GO:0006355 GO:0046782 GO:0006351 IPR007031
$$<002L_FRG3G Uncharacterized protein 002L; GO:0033644 GO:0016021 IPR004251
chomp if !eof
파일의 마지막 줄을 제외한 모든 입력 줄에서 개행을 제거합니다.if($. > 1)
1보다 큰 줄 번호를 입력하세요.print /\$\$</ ? "\n" : "\t"
줄이 일치하면 개행을 추가하고$$<
, 그렇지 않으면 탭하세요.print
입력 라인 인쇄
답변3
아마도 32비트 제한이 있어서 스트리밍만 가능합니다. 당신은 awk
다음과 같은 것을 사용할 수 있습니다
awk 'NR==1 {printf "%s",$0; next;} $1~/^\$\$</ {printf "\n%s",$0; next;} {printf "\t%s",$0;}' < file
$$<
이렇게 하면 첫 번째 줄바꿈으로 시작하는 줄(첫 번째 줄 이후)을 제외하고 줄바꿈 없이 모든 입력 줄이 연속적으로 인쇄됩니다 .
어쩌면 END 섹션이 필요한 마지막 개행 문자를 원할 수도 있습니다. 이러한 변경 사항을 확인하세요 man awk
.
답변4
Ubuntu 12에서 Mawk 및 Gawk 3.x와 함께 작동하며 RS
정규식을 지원합니다.
$ awk 'BEGIN { RS="\\$\\$<"; FS="\n"; OFS="\t" } NF && $1="$$<"$1' data
산출:
$$<002L_tbfl Putative transcription factor 001R; GO:0006355 GO:0046782 GO:0006351 IPR007031
$$<002L_FRG3G Uncharacterized protein 002L; GO:0033644 GO:0016021 IPR004251
우리는 단순히 $$<
개행 문자를 레코드 구분 기호로 사용하고 개행 문자를 필드 구분 기호로 사용합니다.
이는 다음을 의미합니다.
- 입력이 레코드 구분 기호로 시작하므로 빈 레코드를 얻습니다. 다음 조건을 사용하여 이 문제를 제거합니다
NF
. 필드 수는 0이 아니어야 합니다. $$<
입력에서 제거되었습니다. 우리는 그것을 다시 넣었습니다$1
.
중간에 탭이 있는 필드를 인쇄하려면 탭을 출력 필드 구분 기호( OFS
)로 설정합니다. { print }
모드의 기본 동작이므로 무시합니다.
우리가 수정했다는 사실은 모든 필드 결합을 사용하여 레코드 변수를 업데이트하는 $1
부작용도 있습니다 . 이 업데이트가 없으면 원본 레코드는 개행 등을 포함하여 그대로 인쇄됩니다.$0
OFS