bash 쉘에서 파일의 섹션을 grep하는 방법


5

어떤 string1의 발생과 어떤 string2의 (N 번째) 발생 사이의 줄을 어떻게 grep 할 수 있습니까?

예 :

파일에 행이있는 경우 :

에이
비
기음
디
이자형

에프
지
비
기음
이자형

큐

선을 굵은 체로 만들고 싶습니다 (B로 시작하고 E로 끝나는 선).

grep을 사용하여이 작업을 수행 할 수 있습니까? 또는 다른 유닉스 명령 줄 도구?


이것은 sed에 대한 테스트로 들립니다. 그러나 내 sed-fu는 니콜만큼 좋지 않으므로 가까운 경기를 겨냥하고 있습니다. 수퍼 유저 /questions/513393/converting-strings-in-input-file
— Hennes

답변:


9

grep 이 작업에 적합하지 않은 경우 하나의 도구를 "위로"올려야합니다.

sed -n '/^B/,/^E/p' infile

산출:

B
C
D
E
B
C
E

N 번째 요구 사항에 관해서는, 한 도구를 "위로"즉 awk로 다시 이전하는 것이 가장 쉽다고 생각합니다.

awk '/^B/ { f = 1; n++ } f && n == wanted; /^E/ { f = 0 }' wanted=2 infile

산출:

B
C
E

깃발 f 언제 설정 되나요? /^B/ 때 발생하고 설정되지 않은 /^E/ sed 표기법이 작동하는 것과 같은 방식으로 진행됩니다. n 얼마나 많은 블록이 통과되었는지, 언제 f == 1 && n == wanted 가 true이면 기본 블록이 실행됩니다 ( { print $0 } ).


정확히 무엇을하는지 설명해 주시겠습니까? 나는 send가 입력 스트림을 처리한다는 것을 이해한다. 여기서 구문을 추측하는 것은 정규 표현식 / ^ B / to [,] regexp / ^ E (인쇄하지 말 것) [p] /?
— epeleg

발견 된 두 블록 사이에 분리 기호를 삽입하는 방법이 있습니까?
— epeleg

@epeleg : sed 예제는 여러분이 가정 할 때 작동합니다. 범위에 뒤 따르는 모든 명령은 입력이 그 범위에있는 동안 실행됩니다. 조금 sed로 구분 기호를 삽입하기가 복잡하기 때문에 대신 awk를 사용하고 싶습니다. 최신 편집을 참조하십시오.
— Thor

3

@ Thor 's sed 명령은 구타 될 수 없지만 다음 명령으로 perl 스크립트 괄호 안에 질문의 일부를 처리하려고합니다. "... (N 번째) 발생 ...".

용법:

./script <start-regex> <end-regex> [N]

질문에있는 파일의 예 :

$ ./script "B" "E" < examplefile
B
C
D
E
B
C
E

$ ./script "B" "E" 2 < examplefile
B
C
D
E
F
G
B
C
E

어떤 오류 검사도 없으며 스크립트는 욕심이 없습니다, 즉 A B C D E E F 만 B C D E N = 1로 grep 될 것입니다.


#!/usr/bin/perl

if ($ARGV[2] != "") { $n = $ARGV[2] } else { $n = 1 }
$begin_str = $ARGV[0];
$end_str = $ARGV[1];

while(<STDIN>) {
  if($_ =~ $begin_str) { $flag=1 }             # beginning of match, set flag    
  if($_ =~ $end_str && $flag eq 1) { $i++ }    # i-th occurence of end string

  if($i eq $n) {                               # end of match after n occurences of end string
    $flag=2;
    $i=0; 
  }

  if ($flag ge 1) {                            # append currrent line to matching part
    $out.=$_;
  }

  if($flag eq 2) {                             # after detection of end of match, print complete match
    print $out;
    # print "---\n";                           # separator after a match
    $out="";
    $flag=0;
  }

}

감사. 나는 이것을 미래에도 사용할 수 있지만, 지금은 sed 해결책이 갈 길이라고 믿습니다.
— epeleg

1
이 코드를 다시 보면, 필자는 정확한 요구에 맞게 수정할 수 있기 때문에 정말 좋아합니다. (예를 들어 각 줄의 시작 부분에 반복 번호를 추가하는 것처럼).
— epeleg

줄 단위로 인쇄하는 대신 $ out에 연결하는 이유를 설명 할 수 있습니까?
— epeleg

@epeleg : 줄 단위로 인쇄 할 수 없습니다. (처음에는 그랬습니다) A B D 결과는 B D, "종료 종결 자"는 없지만 E. 그 외에도, 이것은 당신에게 "그 두 발견 된 블록들 사이의 분리 기호"를 넣는 쉬운 방법을 제공합니다. (저는 이것을 지금 스크립트에 주석으로 포함 시켰습니다.)
— mpy

"끝없는 종결 자"에 대한 좋은 지적. 감사.
— epeleg
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.