awk / sed로 여러 번 나타날 수있는 두 마커 패턴 사이의 선을 선택하는 방법


119

두 개의 다른 마커 패턴 사이에 발생하는 선을 사용 awk하거나 sed어떻게 선택할 수 있습니까? 이러한 패턴으로 표시된 여러 섹션이있을 수 있습니다.

예 : 파일에 다음이 포함되어 있다고 가정합니다.

abc
def1
ghi1
jkl1
mno
abc
def2
ghi2
jkl2
mno
pqr
stu

그리고 시작 패턴 abc이고 종료 패턴은 다음 과 mno 같이 출력이 필요합니다.

def1
ghi1
jkl1
def2
ghi2
jkl2

sed를 사용하여 패턴을 한 번 일치시킵니다.

sed -e '1,/abc/d' -e '/mno/,$d' <FILE>

어떠한 방법이 sedawk 파일이 끝날 때까지 반복적으로 수행하는가?

답변:


188

awk필요한 경우 인쇄를 트리거하려면 플래그와 함께 사용하십시오 .

$ awk '/abc/{flag=1;next}/mno/{flag=0}flag' file
def1
ghi1
jkl1
def2
ghi2
jkl2

어떻게 작동합니까?

  • /abc/이 텍스트가있는 줄과 일치합니다 /mno/.
  • /abc/{flag=1;next}flag텍스트 abc가 발견 되는 시기를 설정합니다 . 그런 다음 줄을 건너 뜁니다.
  • /mno/{flag=0}flag텍스트 mno가 발견 되면 설정을 해제합니다 .
  • 마지막이 flag되는 기본 동작과 패턴 인 print $0경우 : flagIS는 줄이 인쇄된다 (1)과 동일.

패턴이 표시되거나 표시되지 않는 경우와 함께 자세한 설명과 예 는 두 패턴 사이의 선을 선택하는 방법을 참조하세요 . .


30
패턴을 포함 하여 사이의 모든 것을 인쇄 하려면 awk '/abc/{a=1}/mno/{print;a=0}a' file.
SCAI

6
네, @scai! 또는 심지어 awk '/abc/{a=1} a; /mno/{a=0}' file-이것으로 설정하기 전에 행을 true로 평가하고 인쇄하도록 만들기 a전에 조건 /mno/을 두십시오 a=0. 이런 식으로 우리는 쓰기를 피할 수 있습니다 print.
fedorqui 'SO stop harming'2013

12
@scai @fedorqui 패턴 출력을 포함를 들어, 당신이 할 수있는awk '/abc/,/mno/' file
Jotne

1
@hkasera awk '/abc/{flag=1}/mno/{flag=0}flag' file가 만들어야합니다.
fedorqui 'SO stop harming'2014

2
@EirNym은 매우 다른 방식으로 처리 할 수있는 이상한 시나리오입니다. 어떤 줄을 인쇄 하시겠습니까? 아마 awk 'flag; /PAT1/{flag=1; next} /PAT1/{flag=0}' file만들 것 입니다.
fedorqui 'SO stop harming'Apr

45

사용 sed:

sed -n -e '/^abc$/,/^mno$/{ /^abc$/d; /^mno$/d; p; }'

-n옵션은 기본적으로 인쇄하지 않음을 의미합니다.

패턴은 just abcto just을 포함하는 행을 mno찾은 다음 { ... }. 첫 번째 조치는 abc행을 삭제합니다 . 두 번째 mno줄; 그리고는 p나머지 라인을 인쇄합니다. 필요에 따라 정규식을 완화 할 수 있습니다. abc.. 범위를 벗어난 줄 mno은 인쇄되지 않습니다.


답장과 설명에 감사드립니다! :)
dvai

@JonathanLeffler 내가 사용하는 목적이 무엇인지 알 수-e
Kasun Siyambalapitiya에게

1
@KasunSiyambalapitiya : 주로 사용하고 싶다는 뜻입니다. 공식적으로 다음 인수가 sed실행되어야 하는 스크립트 (의 일부)임을 지정 합니다. 전체 스크립트를 포함하기 위해 여러 인수를 원하거나 사용해야하는 경우 -e각 인수 앞에을 사용해야합니다 . 그렇지 않으면 선택 사항이지만 명시 적입니다.
조나단 레플러

@JonathanLeffler 감사합니다
Kasun Siyambalapitiya

좋은! (저는 awk보다 sed를 선호합니다.) 복잡한 정규 표현식을 사용할 때 반복하지 않아도되는 것이 좋습니다. "선택된"범위의 첫 번째 / 마지막 줄을 삭제할 수 없습니까? 아니면 첫 d번째 일치까지 모든 줄 에 먼저 적용한 다음 d두 번째 일치부터 시작하는 모든 줄에 다른 것을 적용하려면?
hans_meine

18

이것은 당신을 위해 일할 것입니다 (GNU sed) :

sed '/^abc$/,/^mno$/{//!b};d' file

시작 줄 abc과 줄 사이의 줄을 제외한 모든 줄을 삭제합니다.mno



굉장합니다. {//!b}방지 abcmno에서 출력에 포함되고,하지만 난 방법을 알아낼 수 없습니다. 설명해 주시겠습니까?
Brendan

1
@Brendan 명령 //!b은 현재 행이 범위와 일치하는 행 중 하나가 아닌 경우 읽습니다. 따라서 해당 행을 인쇄하고 그렇지 않으면 다른 모든 행이 삭제됩니다.
potong

13
sed '/^abc$/,/^mno$/!d;//d' file

뽀통 보다 두 자 더 나은 골프 {//!b};d

빈 슬래시 //는 "마지막으로 사용한 정규식 재사용"을 의미합니다. 그리고 명령은 더 이해하기 쉬운 것과 동일합니다.

sed '/^abc$/,/^mno$/!d;/^abc$/d;/^mno$/d' file

이것은 POSIX 인 것 같습니다 .

RE가 비어있는 경우 (즉, 패턴이 지정되지 않음) sed는 마지막으로 적용된 명령 (주소 또는 대체 명령의 일부로)에 사용 된 마지막 RE가 지정된 것처럼 동작합니다.


1
두 번째 명령도 범위이기 때문에 두 번째 솔루션은 아무것도 끝나지 않을 것이라고 생각합니다. 그러나 처음에 대한 찬사.
potong

@potong 사실! 왜 첫 번째가 작동하는지 더 공부해야합니다. 감사!
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

7

이전 응답의 링크 ksh에서 솔라리스에서 실행되는 나를 위해 한 것은 다음과 같습니다.

sed '1,/firstmatch/d;/secondmatch/,$d'
  • 1,/firstmatch/d: 1 행부터를 처음 찾을 때까지 firstmatch삭제합니다.
  • /secondmatch/,$d: 처음부터 secondmatch파일 끝까지 삭제합니다.
  • 세미콜론은 순서대로 실행되는 두 명령을 구분합니다.

궁금한 점이 있는데, 왜 범위 제한 기 ( 1,)가 앞에 와야 /firstmatch/합니까? 나는 이것이 또한 표현 될 수 있다고 생각한다 '/firstmatch/1,d;/secondmatch,$d'?
Luke Davis

2
"1, / firstmatch / d"는 "1 행부터 처음으로 'firstmatch'를 찾을 때까지 삭제합니다."라고 말합니다. 반면, "/ secondmatch /, $ d"는 " 'secondmatch'의 첫 번째 발생부터 파일 끝까지 삭제"라고 말합니다. 세미콜론은 순서대로 실행되는 두 명령을 구분합니다.
FanDeLaU

2
perl -lne 'print if((/abc/../mno/) && !(/abc/||/mno/))' your_file

awk와 sed 둘 다에 대한 꽤 좋은 대안이므로 perl에 상응하는 것을 아는 것이 좋습니다.
akhan

2

이 같은 것이 나를 위해 작동합니다.

file.awk :

BEGIN {
    record=0
}

/^abc$/ {
    record=1
}

/^mno$/ {
    record=0;
    print "s="s;
    s=""
}

!/^abc|mno$/ {
    if (record==1) {
        s = s"\n"$0
    }   
}

사용 : awk -f file.awk data...

편집 : O_o fedorqui 솔루션은 내 것보다 훨씬 더 / 예쁘다.


3
GNU에서 awk if (record=1)는이어야합니다 if (record==1). 즉, 이중 = 참조 gawk 비교 연산자
George Hawkins

2

2 일치하는 패턴 사이의 텍스트 만 표시 에서 Don_crissti의 답변 ?

firstmatch="abc"
secondmatch="cdf"
sed "/$firstmatch/,/$secondmatch/!d;//d" infile

AWK의 응용 프로그램보다 훨씬 더 효율적 입니다. 여기를 참조 하십시오 .


질문의 요구 사항이 상당히 다르기 때문에 시간 비교를 연결하는 것이별로 의미가 없다고 생각합니다.
fedorqui 'SO stop harming'2015

2
답변을 비교할 몇 가지 기준이 있어야하기 때문에 동의하지 않습니다. 소수만이 SED 신청서를 가지고 있습니다.
Léo Léopold Hertz 준영

0

pattern2도 pattern1과 일치awk 하는 동안 두 패턴 사이에 선을 인쇄하는 데 사용하려고했습니다 . 그리고 pattern1 라인도 인쇄되어야합니다.

예 : 소스

package AAA
aaa
bbb
ccc
package BBB
ddd
eee
package CCC
fff
ggg
hhh
iii
package DDD
jjj

출력이 있어야합니다.

package BBB
ddd
eee

pattern1이 package BBB이고 pattern2는 package \w*입니다. 참고 CCC때문에 문자 그대로 일치시킬 수없는 알려진 값이 아닙니다.

이 경우 @scai awk '/abc/{a=1}/mno/{print;a=0}a' file또는 @fedorqui 모두 awk '/abc/{a=1} a; /mno/{a=0}' file나를 위해 작동 하지 않습니다 .

마침내 나는 awk '/package BBB/{flag=1;print;next}/package \w*/{flag=0}flag' file, haha로 그것을 해결했습니다.

조금 더 노력하면 awk '/package BBB/{flag=1;print;next}flag;/package \w*/{flag=0}' file, pattern2 라인도 인쇄합니다. 즉,

package BBB
ddd
eee
package CCC
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.