동일한 패턴이 여러 번 나타나는 사이에 줄을 인쇄하는 방법은 무엇입니까?

동일한 패턴이 여러 번 나타나는 사이에 줄을 인쇄하는 방법은 무엇입니까?

지정된 검색 패턴과 발생 횟수가 동일한 패턴 사이의 행을 추출해야 합니다.

마찬가지로 검색 패턴의 첫 번째 발생과 두 번째 발생 사이의 행 또는 세 번째와 네 번째 발생 사이의 행을 가져오고 싶습니다. 패턴 사이에 선이 없을 수 있습니다. 패턴 사이에 선이 없으면 출력은 비어 있어야 합니다.

예: -

Line 1
Line 2
Line 3
Pattern
Line 5
Line 6
Line 7
Pattern
Line 8
Line 9
Pattern
Line 11
Line 12
Pattern
Line 13
Pattern
Pattern

첫 번째 발생과 두 번째 발생 사이에 예상되는 출력 라인

Line 5
Line 6
Line 7

세 번째와 네 번째 발생 사이의 경계선

Line 11
Line 12

답변1

기반으로이 답변,

awk '/Pattern/{n+=1}; n % 2 == 1 && ! /Pattern/ {print > "output"((n-1)/2)}' input_file 

설명하다

  • /Pattern/{n+=1}: 일치시 1을 Pattern더합니다 n.
  • n % 2 == 1 && ! /Pattern/: n이 홀수인 경우에만(즉, 각 대체 패턴 이후) 다음을 실행합니다. 또한 Pattern위의 줄을 무시하십시오.
  • {print > "output"((n+1)/2)}': 위의 내용이 true이면 행을 이름이 지정된 파일에 인쇄합니다 outputx. 여기서 xis ((n+1)/2), 즉 output1, output2, output3...

답변2

AWK 방법의 대안

 $ awk -v start=3  '/Pattern/{n++;next};n==start;n==start+1{exit}' input.txt                                                     
Line 11
Line 12

$ awk -v start=2 '/Pattern/{n++;next};n==start;n==start+1{exit}' input.txt                                                      
Line 8
Line 9

설명하다

작동 방식은 매우 간단합니다.

  • 플래그를 사용하여 -v일치하는 패턴을 찾고 다음 줄로 이동하면 /Pattern/{n++;next}증가하는 변수를 정의합니다(이것은 코드의 일부입니다).
  • awk에서는 조건이 true일 경우 자동으로 내용을 인쇄하라는 시그널이 발생하므로 n==start와 같다고 볼 수 있다 n==start{print}.
  • 마지막 코드 블록은 다음 패턴에 도달했는지 확인합니다. n==start+1{exit} . Say we wanted to print lines between 4th and 5th pattern occurrence. This will mean that whenn==4+1` 코드 종료

코드 골프를 하는 경우 start변수를 다음과 같이 변경하여 코드를 단축할 수 있습니다 -v s=1.

awk -v s=3  '/Pattern/{n++;next};n==s;n==s+1{exit}'

가정:

  • GNU awk
  • n우리는 연속 패턴 사이, 즉 일치 패턴 과 패턴 사이를 읽고 있습니다 .n+1

접근 방식을 일반화

패턴 2와 패턴 4 사이의 선을 인쇄하려면 어떻게 해야 합니까? 이전 예제에서 사용한 것과 동일한 트릭을 사용하여 다음과 같은 작업도 수행할 수 있습니다.

$ awk -v start=2 -v finish=4 '/Pattern/{n++;next};n==finish{exit};n>=start' input.txt                                           
Line 8
Line 9
Line 11
Line 12

여기서는 finish어디에서 멈춰야 할지 알기 위해 또 다른 변수를 정의합니다. 이렇게 n==finish하면 줄 인쇄가 중지됩니다. 또한 그것이 n==finish{exit}앞에 온다 n>=start. 이는 우리가 종료해야 하는 같은 줄에서 중복 인쇄를 피할 수 있게 해준다.

답변3

그리고 sed:

sed -n '/Pattern/!d;:a
n;//! {w file1.txt
ba
};:b 
n;//! bb
:c
n;//q;w file2.txt
bc
' file

POSIX를 사용하면 sed스크립트 내에서 파일 이름을 생성할 수 없기 때문에 일치 항목과 중간 항목에 대해 이러한 루프를 3개 수행해야 합니다.

답변4

start=3; # these can only be positive integers
 stop=4; # stop > start

perl -lne "// or print if /Pattern/ && ++\$a == $start ... // && ++\$a == $stop" data.in

Perl 솔루션은 두 피연산자가 트리거처럼 작동하는 범위 연산자를 사용합니다 .... => 첫 번째 피연산자가 false인 한 ...은 false를 반환합니다. 첫 번째 피연산자가 true이면... true를 반환합니다. 두 번째 피연산자가 true가 되어야만 false가 됩니다. 이러한 미묘함은 피연산자 1이 참인 경우 평가되지 않고, 피연산자 1이 거짓인 동안 피연산자 2가 평가되지 않기 때문에 발생합니다.

sed -nE "
   /Pattern/!d
   x
      s/\$/./
      /^[.]{$start}\$/!{x;d;}
   x

   n

   :loop
      p;n
      /Pattern/{
         x
            s/\$/./
            /^.{$stop}\$/q
         x
      }
   bloop
" data.in

sed 솔루션은 예약된 공간을 사용하여 패턴 발생 횟수를 기록합니다. $start 수의 패턴이 표시되지 않는 한 항상 행을 거부합니다. $start-th 패턴에 도달하면 다음 줄을 계속해서 읽고 인쇄하고 $stop-th 패턴이 보이는지 측정하는 루프에 들어갑니다. 우리는 보자마자 재빨리 빠져나갔다.

관련 정보