파일에서 텍스트를 grep하고 텍스트가있는 단락을 표시하는 방법은 무엇입니까?


24

아래는 파일의 텍스트입니다.

Pseudo name=Apple
Code=42B
state=fault

Pseudo name=Prance
Code=43B
state=good

"42B"를 grep하고 위와 같은 텍스트를 다음과 같이 출력해야합니다.

Pseudo name=Apple
Code=42B
state=fault

누구나 grep/ awk/ 사용하여 이것을 달성하는 방법에 대한 아이디어가 sed있습니까?


이 질문에 "grep"만 태그했습니다. 그렇다면 "grep"솔루션만을 찾고 있습니까? 질문에서 awk & sed도 지정하십시오. 태그를 추가 할 수 있습니까? 어제 밤에 질문을 편집했을 때 당신의 의도를 확신하지 못했습니다.
slm

답변:


38

awk

awk -v RS='' '/42B/' file

RS=입력 레코드 구분 기호를 줄 바꿈에서 빈 줄로 변경합니다. 레코드의 필드가 포함 된 경우 레코드를 /42B/인쇄하십시오.

''(null 문자열)은 POSIX에 따라 빈 줄을 나타내는 데 사용되는 마술 값입니다 .

경우 RS는 널 후 기록이 이루어진 시퀀스에 의해 분리되는 <newline>선행 또는 공백 라인 입력의 시작 또는 끝 부분에 빈 레코드가 생성되지한다 후단 플러스 하나 이상의 공백 라인, 및이 <newline>항상 필드 분리되어야한다 FS 의 가치가 무엇이든간에 .

출력 구분 기호는 단일 줄 바꿈으로 유지되므로 출력 단락이 분리되지 않습니다. 출력 단락 사이에 빈 줄이 있도록하려면 출력 레코드 구분 기호를 두 줄 바꿈으로 설정하십시오.

awk -v RS='' -v ORS='\n\n' '/42B/' file

1
우아한 솔루션 +1 그래도 파일을 리디렉션 할 필요는 없습니다.
jasonwryan

손가락이 자동 조종 장치에있었습니다.
llua

2
@jasonwryan, awk ( FILENAME) 내의 파일 이름에 액세스 해야하는 경우가 아니라면 파일 이름을 포함 =하거나 시작하는 -(또는 -) 인 파일 이름의 문제를 피하고 일관된 오류 메시지를 만들고 실행 awk또는 수행 을 피하므로 리디렉션을 사용하는 것은 좋지 않습니다 입력 파일을 열 수없는 경우 다른 리디렉션
Stéphane Chazelas

14

데이터가 항상 그 이전과 이후의 행이되도록 구성되어 있다고 가정하면 grep의 -A(after) 및 -B(before) 스위치를 사용하여 일치 전 1 행과 그 이후 1 행을 포함하도록 지시 할 수 있습니다.

$ grep -A 1 -B 1 "42B" sample.txt
Pseudo name=Apple
Code=42B
state=fault

검색어 앞뒤에 같은 숫자 줄을 원하면 -C(컨텍스트) 스위치를 사용할 수 있습니다 .

$ grep -C 1 "42B" sample.txt
Pseudo name=Apple
Code=42B
state=fault

여러 줄을 일치시킬 때 더 엄격하려면 도구를 사용하여 pcregrep여러 줄의 패턴을 일치 시킬 수 있습니다 .

$ pcregrep -M 'Pseudo.*\n.*42B.*\nstate.*' sample.txt
Pseudo name=Apple
Code=42B
state=fault

위 패턴은 다음과 일치합니다.

  • -M -여러 줄
  • 'Pseudo.*\n.*42B.*\nstate.*'-첫 번째 문자열이 단어로 시작하고 "Pseudo"줄 끝까지 \n문자가오고, 문자열 "42B"이 나올 때까지 문자가오고, 다른 줄 끝 ( \n)이 나올 때까지 문자가 오는 문자열 그룹 과 일치 합니다. "state"뒤에 모든 문자가옵니다.

5
-C(문맥) 바로 가기로서 이용 될 수있는 경우 -A-B동일하다.
David Baggerman

@DavidBaggerman-감사합니다. 답변에 추가했습니다.
slm

왜 다운 투표인가? 이것은 질문에 대한 답변입니다.
slm

4

awk로 비슷하게 쉬운 방법이 있지만 펄에서는 :

cat file | perl -ne 'BEGIN { $/="\n\n" }; print if $_ =~ /42B/;'

기본적으로 파일을 빈 줄로 구분 된 청크로 분할 한 다음 정규식과 일치하는 청크 만 인쇄합니다.


10
이것은 옵션과 속기를 사용cat 하여 쓸모 없고 ; perl -00 -ne 'print if /42B/' file
tripleee

4

grep유닉스의 몇 가지 맛이있다 -p"단락"에 대한 플래그. 나는 AIX가 알고있다 .

grep -p 42B <myfile>

당신이 원하는 것을 정확하게 할 것입니다. YMMV와 GNU grep에는이 플래그가 없습니다.


-p 플래그를 갖는 것은 훌륭합니다. 특히 -v와 함께 사용하면 전체 단락을 출력에서 ​​제외 할 수 있습니다.
IllvilJa

2

빈 줄이없는 다른 펄 솔루션 :

perl -00ne 'if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}' foo

% perl -00ne 'if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}' foo
Pseudo name=Apple
Code=42B
state=fault

% cat foo
Pseudo name=Apple
Code=42B
state=fault

Pseudo name=Prance
Code=43B
state=good

1
또는 triplee이 주석에 쓴 것처럼 짧아서 읽기 쉽습니다 perl -00 -ne 'print if /42B/' file.
mivk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.