여러 패턴을 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
다음 sed
stdin에 대해 실행합니다.
그래서 내가 할 때 :
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
-----
#