일치하는 패턴을 따라 sed 또는 awk a 행으로 인쇄
질문 : 일치하는 패턴이 포함 된 줄 바로 다음에 한 줄을 인쇄하고 싶습니다.
내 버전은 간단한 해결책처럼 보이는 sed
다음 구문을 사용하지 않습니다 +1p
.
sed -n '/ABC/,+1p' infile
여러 awk
줄 처리를하는 것이 더 낫다고 생각 하지만 어떻게해야할지 모르겠습니다.
매우 모호한 "패턴"이라는 단어를 사용하지 마십시오. 항상 "문자열"또는 "정규식"(또는 쉘 "글 로빙 패턴")을 사용하십시오.
원하는 구체적인 답변은 다음과 같습니다.
awk 'f{print;f=0} /regexp/{f=1}' file
또는 정규 표현식 다음에 N 번째 레코드의보다 일반적인 솔루션을 전문화합니다 (아래의 관용구 "c").
awk 'c&&!--c; /regexp/{c=1}' file
다음 관용구는 일치시킬 특정 정규 표현식이 주어진 레코드 범위를 선택하는 방법을 설명합니다.
a) 일부 정규 표현식에서 모든 레코드를 인쇄합니다.
awk '/regexp/{f=1}f' file
b) 일부 정규 표현식 후에 모든 레코드를 인쇄합니다.
awk 'f;/regexp/{f=1}' file
c) 정규식 다음에 N 번째 레코드를 인쇄합니다.
awk 'c&&!--c;/regexp/{c=N}' file
d) 정규 표현식 이후 N 번째 레코드를 제외한 모든 레코드를 인쇄합니다.
awk 'c&&!--c{next}/regexp/{c=N}1' file
e) 정규 표현식 뒤에 N 레코드를 인쇄합니다.
awk 'c&&c--;/regexp/{c=N}' file
f) 정규 표현식 이후 N 레코드를 제외한 모든 레코드를 인쇄합니다.
awk 'c&&c--{next}/regexp/{c=N}1' file
g) 일부 정규 표현식에서 N 레코드를 인쇄합니다.
awk '/regexp/{c=N}c&&c--' file
변수 이름을 "found"의 "f"에서 "count"의 "c"로 변경했습니다. 변수가 실제로 무엇인지를 더 잘 표현할 수 있기 때문입니다.
당신이 흥미를 느끼는 것은 그 경기 이후 의 대사 죠? sed에서는 다음과 같이 수행 할 수 있습니다.
sed -n '/ABC/{n;p}' infile
또는 grep의 A 옵션을 찾고있을 수도 있습니다.
-A NUM, Print NUM lines of trailing context after matching lines.
예를 들어 다음 입력 파일이 있습니다.
foo
bar
baz
bash
bongo
다음을 사용할 수 있습니다.
$ grep -A 1 "bar" file
bar
baz
$ sed -n '/bar/{n;p}' file
baz
도움이되기를 바랍니다.
패턴 (ok Ed, REGEX) 뒤에 모든 줄을 인쇄해야했기 때문에 다음과 같이 결정했습니다.
sed -n '/pattern/,$p' # prints all lines after ( and including ) the pattern
하지만 이후 모든 줄을 인쇄하고 싶었 기 때문에 (패턴 제외)
sed -n '/pattern/,$p' | tail -n+2 # all lines after first occurrence of pattern
나는 당신의 경우 head -1
끝에 추가 할 수 있다고 생각합니다.
sed -n '/pattern/,$p' | tail -n+2 | head -1 # prints line after pattern
awk 버전 :
awk '/regexp/ { getline; print $0; }' filetosearch
패턴이 일치하면 다음 줄을 패턴 버퍼에 복사하고 반환을 삭제 한 다음 종료합니다. 부작용은 인쇄하는 것입니다.
sed '/pattern/ { N; s/.*\n//; q }; d'
일치 라인이 다음 과 같은 sed -n '/pattern/{n;p}' filename
경우 실제로 실패합니다 .pattern
continuous
$ seq 15 |sed -n '/1/{n;p}'
2
11
13
15
예상 답변은 다음과 같아야합니다.
2
11
12
13
14
15
내 솔루션은 다음과 같습니다.
$ sed -n -r 'x;/_/{x;p;x};x;/pattern/!s/.*//;/pattern/s/.*/_/;h' filename
예를 들면 :
$ seq 15 |sed -n -r 'x;/_/{x;p;x};x;/1/!s/.*//;/1/s/.*/_/;h'
2
11
12
13
14
15
설명 :
x;
: 입력에서 각 줄의 시작 부분에서x
명령을 사용 하여pattern space
& 의 내용을 교환하십시오hold space
./_/{x;p;x};
: ifpattern space
, which is thehold space
actually, contains_
(this is just aindicator
indicating if last line matched thepattern
or not), then usex
to exchange the actual content ofcurrent line
topattern space
, usep
to printcurrent line
, andx
to recover this operation.x
: recover the contents inpattern space
andhold space
./pattern/!s/.*//
: ifcurrent line
does NOT matchpattern
, which means we should NOT print the NEXT following line, then uses/.*//
command to delete all contents inpattern space
./pattern/s/.*/_/
: ifcurrent line
matchespattern
, which means we should print the NEXT following line, then we need to set aindicator
to tellsed
to print NEXT line, so uses/.*/_/
to substitute all contents inpattern space
to a_
(the second command will use it to judge if last line matched thepattern
or not).h
: overwrite thehold space
with the contents inpattern space
; then, the content inhold space
is^_$
which meanscurrent line
matches thepattern
, or^$
, which meanscurrent line
does NOT match thepattern
.- the fifth step and sixth step can NOT exchange, because after
s/.*/_/
, thepattern space
can NOT match/pattern/
, so thes/.*//
MUST be executed!
This might work for you (GNU sed):
sed -n ':a;/regexp/{n;h;p;x;ba}' file
Use seds grep-like option -n
and if the current line contains the required regexp replace the current line with the next, copy that line to the hold space (HS), print the line, swap the pattern space (PS) for the HS and repeat.
ReferenceURL : https://stackoverflow.com/questions/17908555/printing-with-sed-or-awk-a-line-following-a-matching-pattern
'programing' 카테고리의 다른 글
XSL xsl : 템플릿 일치 =“/” (0) | 2021.01.16 |
---|---|
echo 문 안에 블록이 있습니까? (0) | 2021.01.16 |
각도기를 Enter 키를 누르는 방법은 무엇입니까? (0) | 2021.01.16 |
Android에서 카드 뷰 주변의 그림자를 비활성화하는 방법 (0) | 2021.01.16 |
SQL 언어가 구성되지 않음 (Phpstorm) (0) | 2021.01.16 |