programing

일치하는 패턴을 따라 sed 또는 awk a 행으로 인쇄

shortcode 2021. 1. 16. 20:23
반응형

일치하는 패턴을 따라 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경우 실제로 실패합니다 .patterncontinuous

$ 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

설명 :

  1. x;: 입력에서 각 줄의 시작 부분에서 x명령을 사용 하여 pattern space& 의 내용을 교환하십시오 hold space.
  2. /_/{x;p;x};: if pattern space, which is the hold space actually, contains _ (this is just a indicator indicating if last line matched the pattern or not), then use x to exchange the actual content of current line to pattern space, use p to print current line, and x to recover this operation.
  3. x: recover the contents in pattern space and hold space.
  4. /pattern/!s/.*//: if current line does NOT match pattern, which means we should NOT print the NEXT following line, then use s/.*// command to delete all contents in pattern space.
  5. /pattern/s/.*/_/: if current line matches pattern, which means we should print the NEXT following line, then we need to set a indicator to tell sed to print NEXT line, so use s/.*/_/ to substitute all contents in pattern space to a _(the second command will use it to judge if last line matched the pattern or not).
  6. h: overwrite the hold space with the contents in pattern space; then, the content in hold space is ^_$ which means current line matches the pattern, or ^$, which means current line does NOT match the pattern.
  7. the fifth step and sixth step can NOT exchange, because after s/.*/_/, the pattern space can NOT match /pattern/, so the s/.*// 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

반응형