너무 길어요.

너무 길어요.

기본적으로 두 문자열 사이의 내용을 가져오려고 하는데 다음과 같이 동일한 문자를 N 번 반복합니다.

===
This is a test
===

====
Another test
====

==
Last test
==

물론 위의 내용은 단지 예시일 뿐이다. 내 시도와 결과는 다음과 같습니다.

sed -u '/==/!d;s//&\n/;s/.*\n//;:a;/==/bb;$!{n;ba};:b;s//\n&/;P;D' testfile

주다

=
This is a test

=




Another test






Last test


위 중 하나를 사용하는 경우 testfile:


Last test


이렇게 하면 원하는 결과를 얻을 수 있습니다(비록 줄바꿈이 너무 많이 추가되기는 하지만 이 예에서는 괜찮습니다).

위의 방법은 이러한 반복 문자의 인스턴스가 하나만 있거나 내용이 포함된 고유 문자열 쌍인 경우에만 작동합니다.

반복되는 문자 수가 동일한 두 문자열 사이의 내용을 얻는 방법은 무엇입니까? 나는 이것을 사용하거나 grep이를 달성하는 것을 sed선호 합니다.awk

답변1

우리는 사용다음과 같은 트리거 로직을 사용하여 열린 상태에서 닫힌 상태로 전환하는 유틸리티입니다.

$ awk -v str="==" '
      $0""==str{f=!f;next};f
' testfile
Last test

Posixly 사용sed트리거 로직의 구성을 구현할 수 있습니다.

sed -ne '
  /^==$/{
    x;        # access state info from hold
    s/^$/0/;  # initialize state
    y/01/10/; # toggle state
    x;        # save state in hold
    d;        # next
  }
  G;/\n1/P
' testfile

스트림 편집기의 GNU 버전 사용sed확장 모드에서-E

$ sed -Ee '
    $!N; /^(\S)\1+\n/!D
    :loop
        $d;N
        s/^(.*)\n(.*)\n\1$/\2/;t
    bloop
' testfile
This is a test
Another test
Last test

노트:-

  • 명령을 통해 N두 줄 패턴 공간을 유지합니다 .
  • 황금색 라인에 도달할 때까지 라인을 계속 거부합니다(=> 패턴 공간의 첫 번째 부분에 공백이 아닌 문자의 단일 유형만 포함되어 있음).
  • 그러한 선을 찾으면 도로에서 선과 정확히 일치하는 복제본이 두 개 이상 나타날 때까지 반복합니다. 우리는 첫 번째 그룹을 찾았습니다.
  • eof에 도달할 때까지 이 과정을 반복합니다.

...트리거 연산자 사용진주다음과 같이 이를 수행할 수 있습니다.

perl -lne 'print if 
 /^(\S)\1+$(?{$a=$_})/ ... $_ eq $a and $_ ne $a;
' testfile

고정된 미리 결정된 문자열을 검색하는 것이 훨씬 더 간단합니다. 그 이후에는 정규식을 작성할 필요가 없고 문자열 동등성 테스트만으로 충분합니다.

$ perl -nlse 'print if
    $_ eq $a ... $_ eq $a and $_ ne $a;
' -- -a=== testfile

$ sed -Ee '
    /^==$/!d
    $!N
    :a
        $d;N
        s/^(.*)\n(.*)\n\1$/\2/;t
    ba
' testfile

답변2

너무 길어요.

$ sed '/^==*$/,//{//!p};d' testfile
This is a test
Another test
Last test

언뜻 보기에 간단한 범위는 모든 쌍을 인쇄합니다(루핑이 필요하지 않음).

$ sed -n '/^=/,//p' testfile
===
This is a test
===
====
Another test
====
==
Last test
==

=( )로 시작하는 줄 과 다음 반복되는 정규식( ) //사이의 모든 줄을 인쇄합니다 .

라인으로 개선할 수 있습니다.오직포함하다 =: /^==*$/.

모든 마커를 제거합니다.

$ sed -n '/^==*$/,//H;${x;s/\n==*//g;s/^\n//;p}' testfile
This is a test
Another test
Last test

또는 더 짧은 형식으로:

$ sed -n '/^==*$/,//{//d;p}' testfile
This is a test
Another test
Last test

정확한 수량을 일치시키려면 =정규 표현식을 다음과 같이 변경하세요.

$ sed -n '/^==$/,//{//d;p}' testfile
Last test

그리고 해당 -n옵션을 피하려면 다음을 수행하십시오.

$ sed '/^==$/,//{//!p};d' testfile
Last test

awk에서는 다음과 같이 할 수 있습니다.

$ awk 'p==0 && /^==*$/ {p=1;next}
       p==1 && /^==*$/ {p=0}
       p          
      ' testfile

This is a test
Another test
Last test

또는 덜 명시적인 형태로:

awk ' /^==*$/ { p = !p ; next}
      p
    ' testfile

답변3

나는 다음을 사용할 것이다 perl:

$ perl -0777 -ne 'print $3 while /^((\S)\2+\n)(.*?)^\1/smg' < your-file
This is a test
Another test
Last test

또는 pcregrep:

$ pcregrep -Mo3 '(?s)^((\S)\2+\n)(.*?)\n?^\1' < your-file
This is a test
Another test
Last test

고정 구분 기호 사이의 콘텐츠를 반환하는 경우:

$ pcregrep -Mo1 '(?s)^==\n(.*?)\n?^==$' < your-file
Last test

답변4

주문하다:

awk '{a[++i]=$0}/==/{for(x=NR-1;x<NR;x++)print a[x]}' filename|sed '/^$/d'

산출

This is a test
Another test
Last test

관련 정보