2014-09-11 3 views
2

여기에서 검색 중이지만 가까이에 있지만 여전히 시도하고있는 것처럼 보이지 않습니다. 예. 다음 예제 테스트 입력을 고려해보십시오. 목표는 "abc"(이 줄 인쇄) 줄이 포함 된 줄부터 "efg"줄 (이 줄 인쇄)로 끝나는 여러 줄에 걸쳐있는 일치 항목을 찾는 것입니다. 사이에 줄을 인쇄하십시오.여러 줄에 걸쳐 복잡한 일치가 발생했습니다.

yyabc} 
000 
iiabc< 
    {efg+1} 
111 
yyabc} 
222 
p {efg+13} 
zzz 
    z {efg+243} {} 
iii 
oooabc> 
ooo 

위의 라인 테스트 입력 파일로 ZZZ로, 나는이 무엇을 찾고 있어요 회의에 온 그 가장 가까운,

sed -e '/abc/,/efg/!d' zzz 

하지만, 별도의 라인을 포함, 즉 상관 없어

yyabc} <<***** extra 
000  <<***** extra 
iiabc< 
    {efg+1} 
yyabc} 
222 
p {efg+13} 
oooabc> <<***** extra 
ooo  <<***** extra 

,이없는, 즉, 출력이 예상

iiabc< 
    {efg+1} 
yyabc} 
222 
p {efg+13} 

pcregrep에 의존하는 것 외에 (나는 리눅스 상자에있는 모든 것을 가지고있다.) 그런 다중 라인을 일치시킬 수있는 솔루션이 있는가?

감사합니다.

답변

1

awk에 패턴까지 텍스트의 "동일한"부분에서 어떤 이전의 ABC와 EFG와 같은 라인에있는 경우 작업에 적합하지 않습니다 이 작업. 당신이 입력 파일이 zzz라고 테스트 경우, 실행

$ awk '/abc/{a=""} /abc/,/efg/{a=a"\n"$0} /efg/{print substr(a,2);a=""}' zzz 
iiabc< 
    {efg+1} 
yyabc} 
222 
p {efg+13} 

설명 :

  • /abc/{a=""}

    "ABC"를 포함하는 행에 도달 할 때마다, 설정 변수 a에 빈 문자열 (우리가 인쇄 할 선이 다음 단계에서이 변수에 추가됩니다.)

  • abc을 포함하는 행으로 시작 efg를 포함하는 라인으로 끝나는 라인의 모든 범위에 걸쳐 /abc/,/efg/{a=a"\n"$0}

    , 각 줄은 변수 a에 추가됩니다. 범위의 마지막 줄에 도달하면

  • /efg/{print substr(a,2);a=""}

    a을 인쇄 할 수 있습니다.a이 개행 문자로 시작하기 때문에 substr을 사용하여 제거합니다.

위의 첫 번째 단계가 없으면 프로그램이 제대로 실행되지만 "추가"줄이 인쇄됩니다. 첫 번째 단계가 포함되면 제거됩니다.

+0

감사. 네, 이것도 작동하며 파일 크기가 2793383645 인 동일한 테스트 입력을 사용하여 올바르게 작동하는 것으로 확인되었습니다. – dinan5m3

+0

나는 그것을 이해할 수 있기 때문에 나는이 대답을 좋아한다. 모두에게 감사드립니다! – dinan5m3

0

이것을 사용해보십시오.

데모보기

http://regex101.com/r/bA0jG5/11

마지막 ABC 라인 전에 줄을 제거보다, ABC 먼저 EFG의 일부를 잡을 수있는 버퍼의
+0

이 유는 무엇을 얻었 는가? – vks

+0

젠장, 어떻게이 stackoverflow에 논평합니까 ?????? 감사합니다. 나는 그것을 시도하고 따르고있다, '$ cat zzz | perl -n000e 'print $ & while while /(.*? abc (? :(? :(?! efg | abc).) | \ n) * efg. * $)/gm " 닫기. 다음과 같이 수정하여 예상 결과를 얻은 것으로 보입니다. '$ cat zzz | perl -n000e 'print $ & while /(.*? abc (? :(? :(?! efg | abc).) | \ n) * efg. * $. * \ n)/gm " – dinan5m3

+0

@ dinan5m3 그것은 당신의 질문에 답하는 것을 옳은 것으로 표시하는 것을 잊지 마십시오. – vks

1
sed -n '/abc/,/efg/ { 
    H 
    /efg/ { 
     g 
:a 
     s/^.*\n\(.*abc\)/\1/ 
     ta 
     p 
     } 
    }' zzz 

사용은 마지막으로 결과를 인쇄 텍스트의 나머지를 계속합니다.

ABC 방송은 한 줄에 patterne에서 //,// 일을 나오지 때문에 다른 회선

+0

감사합니다. 그것을 시도하고 작동합니다. 또한 실제 테스트 입력 인 2793383645의 파일 크기와 비교해 보았습니다. – dinan5m3

+0

좋은 sed 검은 마법;) – klashxx

0

직접적인 배열 기반 AWK 솔루션 :

awk '/abc/ {delete a;j=0;flag=1} 
    flag {a[++j]=$0} 
    /efg/ && flag {for (i=1;i<=j;i++){print a[i]};flag=0}' inputfile 

/abc/ {delete a;j=0;flag=1} : 초기 패턴을 찾을 때, 카운터를 0으로 설정 한 배열을 삭제하고 "찾기"플래그를 켭니다.

flag {a[++j]=$0} : 플래그가 켜져있을 때 줄 내용을 저장합니다.

/efg/ && flag {for (i=1;i<=j;i++){print a[i]};flag=0} : 최종 패턴을 발견하고 플래그 때, 배열을 표시하고 전체 파일 slurps 펄 한 줄 사용 플래그

1

의 전원을 끄십시오

perl -0777 -ne 'print /.*abc.*\n(?:(?!.*(?:abc|efg)).*\n)*.*efg.*\n/g' file.txt 

또는 라인으로 라인을 완충 용액 :

perl -ne ' 
    $b = /abc/ ? $_ : "$b$_"; 
    print $b if (/abc/ .. /efg/) =~ /E/ 
    ' file.txt 

스위치 : 0

  • -0777 : 전체 파일을 슬럿합니다.
  • -n : 입력 파일에 각 “ 행 ”에 대해 while(<>){...} 루프를 생성합니다.
  • -e : perl에게 명령 줄에서 코드를 실행하도록 지시합니다.
1

당신 (GNU이 나오지도)에 대한이 작동하지 않을 수 있습니다 :

-n 스위치를 호출하여 "그렙"모드에서 나오지도 사용
sed -n '/abc/,/efg/{/abc/{h;d};H;/efg/{g;p}}' file 

. abc과 efg` 사이의 관심 대상을 필터링하십시오. 홀드 스페이스 (HS)를 사용하여 포함 라인을 저장 한 다음 프린트하십시오.

대안 : dinan5m3 @

sed -n '/abc/,/efg/{/abc/h;//!H;/efg/{x;p}}' file 
관련 문제