여러 패턴을 Grep하고 각 패턴에서 서로 다른 줄 수를 인쇄하시겠습니까?

여러 패턴을 Grep하고 각 패턴에서 서로 다른 줄 수를 인쇄하시겠습니까?

여러 패턴을 grep/awk한 다음 첫 번째 패턴 아래에 특정 수의 줄을 인쇄하고 두 번째 패턴 아래에 특정 수의 줄을 인쇄하는 방법을 찾으려고 합니다. 예를 들어

  ....
  other lines
  ....
###Pattern 1####
line 1
line 2
line 3 
 ....
 other lines
 ....
####Pattern 2####
line 1
line 2
line 3 
line 4
 ....
 other lines
 ....

그래서 내가 하고 싶은 것은 파일에서 두 개의 패턴을 찾아 첫 번째 패턴과 그 아래 처음 3줄을 인쇄한 다음 두 번째 패턴과 그 아래 처음 4줄을 인쇄하는 것입니다.

이렇게 하면 내가 원하는 출력은 다음과 같습니다.

####Pattern 1####
line 1
line 2
line 3
####Pattern 2####
line 1
line 2
line 3 
line 4

업데이트된 필수 출력 너무 명확하게 설명하기 전에 사과드립니다. 여러 패턴이 있을 수 있습니다. 그래서 제가 달성하고자 하는 것은 다음과 같은 결과입니다.

####Pattern 1####
line 1
line 2
line 3
####Pattern 2####
line 1
line 2
line 3 
line 4
-----
####Pattern 1####
line 1
line 2
line 3
####Pattern 2####
line 1
line 2
line 3 
line 4
-----
 and so on

답변1

sed -ne'/pattern1/{:1' -e'$p;N;s/\n/&/[num]; to' -eb1 -e\} \
     -e'/pattern2/{:2' -e'$p;N;s/\n/&/[num]; to' -eb2 -e\} \
     -ed -e:o -eh      -e'y/\n-/-\n/;s/[^-]*//g' -e'H;x;p'

-일치 블록 뒤에 줄 바꿈이 있는 만큼 많은 대시가 인쇄 됩니다 . 따라서 각 패턴 1 일치 뒤에 4줄, 각 패턴 2 일치 뒤에 2줄을 원한다면 패턴 1 블록 끝에 4개의 하이픈이 있고 패턴 2 블록 끝에 2개의 하이픈이 있습니다. 각 블록 사이에 선이 있습니다. 다 사실이야와는 별개로각 꼬리를 수집하는 동안 마지막 줄이 발견되면 - 이 경우 마지막 줄과 패턴 일치 사이의 모든 내용이 인쇄되지만 하이픈은 추가되지 않습니다.

위 스크립트의 코드 중 상당수가 sed상당히 중복되어 있음을 알 수 있습니다. 기본적으로 우리는 가능한 모든 일치에 대해 동일한 유형의 루프를 구현합니다. 위에서 설명한 것처럼 스크립팅을 훌륭하게 sed만드는 것은 매우 간단한 구문 규칙입니다 . sed즉, sed구문이 매우 기본적이므로 스크립트 가능한 sed스크립트를 작성하는 것은 간단한 문제입니다.

예를 들어, 이 작업은 원하는 수의 패턴과 연관된 다음 행 수를 처리하도록 쉽게 매개변수화할 수 있습니다.

amatch(){  sed ${2:+"-ne$(n=0;                   \
    while  [ "$#" -gt "$((!!(n+=1)))" ];         \
    do     printf "\n/%s/{:$n\n\t%s;to\n\t%s\n}" \
                  "$1" "\$p;N;s/\n/&/$2" "b$n";  \
           shift 2;                              \
    done;  printf "\nd;:o\n\t%s\n\t%s\n\tH;x;p"  \
                  'h;y/\n-/-\n/' 's/[^-]*//g'    \
)"}; }

amatch()2개 이상의 인수로 호출 될 때마다 sed위와 같은 스크립트를 작성하고 각 쌍에 대해 루프를 작성합니다.

따라서 먼저 subshell에서 스크립트를 빌드하고 인쇄한 sed다음 sedstdin에 대해 실행합니다.

그래서 내가 할 때 :

seq 30 | amatch \[45] 5 1$ 2

쉘의 while 루프는 아래와 같이 명령 대체 스크립트를 조합하고 인쇄합니다.

/[45]/{:1
    $p;N;s/\n/&/5;to
    b1
}
/1$/{:2
    $p;N;s/\n/&/2;to
    b2
}
d;:o
    h;y/\n-/-\n/
    s/[^-]*//g
    H;x;p

sed표준 입력 및 인쇄에 대해 평가합니다 .

1
2
3
--
4
5
6
7
8
9
-----
11
12
13
--
14
15
16
17
18
19
-----
21
22
23
--
24
25
26
27
28
29
-----

답변2

더 우아한 방법이 있다는 것은 의심의 여지가 없지만 이것이 하나의 접근 방식입니다.

# awk '/Pattern 1/{for(c=0;c<4;c++){print;getline}}/Pattern 2/{for(c=0;c<5;c++){print;getline}}' foo
###Pattern 1####
line 1
line 2
line 3
####Pattern 2####
line 1
line 2
line 3
line 4
#

좀 더 우아하게:

# awk '/Pattern 1/{c=4}/Pattern 2/{c=5}{while(c-->0){print;getline}}' foo
###Pattern 1####
line 1
line 2
line 3
####Pattern 2####
line 1
line 2
line 3
line 4
#

일치하는 세트 아래에 5개의 하이픈을 표시하려면 다음을 시도하십시오.

# awk '/Pattern 1/{c=4}/Pattern 2/{c=5}{while(c-->0){print;getline;x=1}if(x){print "-----";x=0}}' foo
###Pattern 1####
line 1
line 2
line 3
-----
####Pattern 2####
line 1
line 2
line 3
line 4
-----
#

또는 끝에 "------"를 사용하십시오.

# awk '/Pattern 1/{c=4}/Pattern 2/{c=5}{while(c-->0){print;getline}}END{print "-----"}' foo
###Pattern 1####
line 1
line 2
line 3
####Pattern 2####
line 1
line 2
line 3
line 4
-----
#

관련 정보