동일한 패턴 사이의 awk 또는 sed 라인(첫 번째 일치 포함)

동일한 패턴 사이의 awk 또는 sed 라인(첫 번째 일치 포함)

다음은 텍스트입니다.

* Tue This is the first line

– info 1

– info 2

– info 3

* Wed This is not to be included

이 텍스트의 출력은 다음과 같아야 합니다.

* Tue This is the first line

– info 1

– info 2

– info 3

참고: awk 및 sed를 시도했지만 출력을 얻지 못했습니다. 문제는 START와 END가 동일한 "*"(별표)이고 첫 번째 항목이 출력에 포함되어야 한다는 것입니다.

답변1

나는 이것을 올바르게 이해하기를 바랍니다. 이 스크립트는 두 번째 줄부터 버퍼 끝까지 *모든 것을 제거하여 예제에서 원하는 출력을 생성합니다.

sed -n 'H;1h;$x;$s/\(\*[^*]*\)\n\*.*$/\1/p'

설명 H보유 버퍼에 모든 라인( )을 추가합니다. 마지막 라인에서는 홀드 버퍼와 패턴 버퍼( $x)를 교체하여 전체 파일을 하나의 패턴으로 갖게 됩니다. 이 모드에서는 유지될 부분이 설정 \(\)및 유지되며( \1), 개행 안의 모든 내용은 *제거됩니다.

이는 설명에 적합하지만 가능한 모든 예에 맞지 않으면 스크립트를 수정할 수 있습니다.

답변2

perl -lne 'if ( m?^\*? ... m?^\*? ) { print if !// || !$a++ }'

sed -e '
   /^\*/!d
   :loop
       $q; N
   /\n\*/!bloop
   s/\(.*\)\n.*/\1/;q
'

sed -e '
   /^\*/!d
   :loop
      n
   //!bloop
   Q
'

답변3

샘플 텍스트를 변수에 저장합니다.

$ SAMPLE=$(cat <<EOF
* Tue This is the first line

– info 1

– info 2

– info 3

* Wed This is not to be included
* Tue This is the first line

– info 1

– info 2

– info 3

* Wed This is not to be included
EOF
)

처리 awk방법 $SAMPLE:

$ awk '{if($1~"\*"){if(p==1){p=0;next}else{p=1}}if(p==1){print $0}}' <<<"$SAMPLE"
* Tue This is the first line

– info 1

– info 2

– info 3

* Tue This is the first line

– info 1

– info 2

– info 3

편집하다

의견에서 제안한 것처럼 놀랍도록 우아한 awk솔루션이 있습니다.

$ awk '/^\*/{p=!p};p' <<<"$SAMPLE"
* Tue This is the first line

– info 1

– info 2

– info 3

* Tue This is the first line

– info 1

– info 2

– info 3

작동 방식:

  • /^\*/{p=!p};p- 의 값이 바뀌게 됩니다 1. 정규식을 처음 발견하면 0가 됩니다. 두 번째로 발견되면 그렇게 됩니다.1/^\*/p0

  • p- 이는 와 동일합니다 p{print}. 는 의 기본 작업이므로 print전제 조건이 해당 값으로 평가될 때(이 경우 가 될 때 ) awk항상 인쇄됩니다 .truep1

관련 정보