sed - 행이 조건과 일치하면 패턴 범위와 일치하는 행을 인쇄합니다.

sed - 행이 조건과 일치하면 패턴 범위와 일치하는 행을 인쇄합니다.

처리해야 하는 여러 줄의 로그 항목 형식이 있습니다.

로그는 다음과 같습니다.

--START--
Device=B
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=A
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=B
Data=asdfasdf
--END--
--START--
Device=A
Data=asdfasdf
--END--
--START--
Device=B
Data=asdfasdf
--END--
--START--
Device=C
Data=asdfasdf
Lorem=Ipsum
--END--

특정 패턴이 일치하는 경우 --START--사이의 모든 내용을 인쇄하고 싶습니다 .--END--

예를 들어:

모든 항목 인쇄Device=A

--START--
Device=A
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=A
Data=asdfasdf
--END--

지금까지 내가 할 수 있는 일은 다음과 같이 쓰는 것 뿐이다.

sed -e -n '/--START--/,/--END--/p' < input

{}입력값을 효과적으로 출력하는데, 필터를 추가 N한 뒤 조건이 일치하면 출력 해야 할 것 같습니다 .

나도 완전히 길을 잃은 것 같은 느낌이 든다.

한 줄이 조건과 일치하는 경우 여러 줄을 인쇄하는 방법을 알고 있습니까?

답변1

$ sed -n '/--START--/{:a;N;/--END--/!ba; /Device=A/p}' file
--START--
Device=A
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=A
Data=asdfasdf
--END--

(위 내용은 GNU sed에서 테스트되었습니다. BSD/OSX에서 실행되도록 조정해야 합니다.)

작동 방식:

  • /--START--/{...}

    포함된 행에 도달할 때마다 --START--중괄호 안의 명령이 실행됩니다 {...}.

  • :a

    라벨을 정의합니다 a.

  • N

    다음 줄을 읽고 패턴 공간에 추가하세요.

  • /--END--/!ba

    패턴 공간에 현재 레이블이 포함되어 있지 않으면 --END--레이블로 다시 이동합니다 a.

  • /Device=A/p

    여기까지 오면 패턴 공간이 로 시작 --START--하고 으로 끝난다는 뜻입니다 --END--. 추가적으로, 패턴 공간에 그것이 포함되어 있다면 Device=A, 그것을 인쇄( p)하세요.

답변2

sed예약된 공간을 사용한 기타 변형

sed 'H              #add line to hold space
     /--START--/h   #put START into hold space (substitute holded in)
     /--END--/!d    #clean pattern space (start next line) if not END
     x              #put hold space into pattern space
     /Device=A/!d   #clean pattern space if it have not "Device=A"
    ' file

답변3

그리고 sed:

$ -e:1 -e'$!N;/--END--/{
  /Device=A/!d
  b
}' -eb1 <file
--START--
Device=A
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=A
Data=asdfasdf
--END--

--START--그러면 패턴 공간 사이와 패턴 공간 사이의 모든 줄이 읽혀집니다 --END--. 일치하면 --END--패턴 공간에 포함되어 있지 않은지 확인하고 Device=A삭제하고, 그렇지 않으면 sed패턴 공간을 인쇄하고 다음 루프를 시작합니다.

그리고 awk:

awk '
  /--START--/ {
    getline d
    if (d ~ /Device=A/) {
      p = 1
      printf "%s\n%s\n", $0, d
      next
     }
  }
  p
  /--END--/ { p = 0 }
' <file

답변4

여기에는 문자열 사이의 문자열을 테스트하는 방법을 보여주는 몇 가지 다른 좋은 답변이 이미 있습니다.--START--그리고--END--그러나 예제 입력을 고려하면 실제로 걱정할 필요는 없습니다.--START--별말씀을요.

sed -n '$!N;/^Device=A\n/,/\n--END--/P;D'

...모든 것을 인쇄합니다Device=A\n다음 항목이 발생할 때까지 발생하는 마지막 Ewline--END--각 블록에. 괜찮아요--START--굳이 확인할 필요는 없을 것 같기 때문이다.

따라서 다음과 같은 블록의 경우:

--START--
Device=A
...stuff...
--END--

...출력은 다음과 같습니다.

Device=A
...stuff...

...하지만 이런 블록의 경우에는...

--START--
Device=B
Device=A
...stuff...
--END--

...같은 결과가 출력됩니다.

N마지막 줄이 아닌 모든 줄 에 추가 입력 줄을 추가하여 작동하므로 패턴 공간은 다음과 같습니다.!$

^line1\nline2$

시퀀스 사이에 발생하는 모든 패턴 공간에 대해^Device=A\n그리고\n--END--현재 패턴의 두 줄 중 첫 번째 줄이 P인쇄된 후 D삭제되고 나머지 내용으로 다음 루프가 시작됩니다. 다음 패턴 공간은 다음과 같습니다.

^line2\nline3$

관련 정보