지정된 검색 패턴과 발생 횟수가 동일한 패턴 사이의 행을 추출해야 합니다.
마찬가지로 검색 패턴의 첫 번째 발생과 두 번째 발생 사이의 행 또는 세 번째와 네 번째 발생 사이의 행을 가져오고 싶습니다. 패턴 사이에 선이 없을 수 있습니다. 패턴 사이에 선이 없으면 출력은 비어 있어야 합니다.
예: -
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
. 여기서x
is((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 when
n==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 패턴이 보이는지 측정하는 루프에 들어갑니다. 우리는 보자마자 재빨리 빠져나갔다.