어떤 string1의 발생과 어떤 string2의 (N 번째) 발생 사이의 줄을 어떻게 grep 할 수 있습니까?
예 :
파일에 행이있는 경우 :
에이
비
기음
디
이자형
에프
지
비
기음
이자형
큐
선을 굵은 체로 만들고 싶습니다 (B로 시작하고 E로 끝나는 선).
grep을 사용하여이 작업을 수행 할 수 있습니까? 또는 다른 유닉스 명령 줄 도구?
답변
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 }
).
답변
@ 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;
}
}