일치 후 다음 줄만 인쇄하려면 awk를 사용하십시오.

일치 후 다음 줄만 인쇄하려면 awk를 사용하십시오.

grep, 및 와 같은 다른 도구를 사용하여 awk여러 파이프를 일치시킨 후 직접 라인을 인쇄하는 명령이 있습니다 tail. 이것은 작동하지만 약간 지저분한 느낌이 들고 이 작업을 수행하기 위해 여러 파이프를 사용합니다. 이러한 도구 중 하나를 사용하여 단 하나의 명령으로 이를 수행할 수 있습니까? 파일 끝에 공백 줄도 있습니다.

문서 내용:

10:28:48  2022-09-15T15:28:36Z:    Creating tar ball for build artifacts
--
10:28:53  --> Build complete: Artifacts were created:
file: build-1.tar.gz

주문하다

grep -A1 "Artifacts were created:" $file | tail -n1 | awk '{print $2}'

결과

build-1.tar.gz

이는 기술적으로는 가능하지만 다소 엉성해 보입니다.

답변1

시도해 보십시오:

awk '/Artifacts were created:/{p=1} NF{out=$2}  END{if(p==1){print out}}' infile

제공한 파이프라인은 마지막 필드가 아닌 일치 후 행의 두 번째 필드를 추출하고 있습니다. 이는 awk에 대한 단일 호출로 변환됩니다.

awk '
      # Have we found the match?
      /Artifacts were created:/{ found=1 ; next }
      
      # if a match has been found, print and exit
      found == 1 { print $2; exit }

    ' "$file"

답변2

sed옵션 이라면

$ sed -En '/Artifacts were created:/{n;s/[^ ]* (.*)/\1/p}' <<< "$file"
build-1.tar.gz

답변3

이것원래 요청일치 항목 이후 비어 있지 않은 마지막 줄의 값을 요청합니다. 여기에서 일치하는 트리거를 찾으면 플래그를 설정하세요. 플래그를 설정한 후 파일이 끝날 때까지 기다린 다음 캡처한 마지막 항목을 인쇄합니다.

awk '
    # Set the flag on match
    /Artifacts were created/ { flag++ }

    # Capture second field of a line that is not just whitespace
    NF { lastitem = $2 }

    # At the end, maybe print the last captured item
    END { if (flag) { print lastitem } }
' "$file"

일부 버전에서는 절의 마지막 부분을 awk인용할 수 있습니다 . 여기서는 파일을 탐색할 때 최신 항목을 캡처하는 보다 직접적인 접근 방식을 선호합니다.$2END


업데이트된 요구 사항에서는 일치 항목 바로 다음 행에 값을 제공해야 합니다. 파일을 완전히 처리할 필요가 없기 때문에 이는 훨씬 더 간단하고 더 빠릅니다.

awk '
    # Output second field of line immediately following the flag being set
    flag && NF { print $2; exit }

    # Set the flag on match
    /Artifacts were created/ { flag++ }

' "$file"

답변4

사용행복하다(이전 Perl_6)

~$ raku -e 'put $<>.words[1] if m{ "Artifacts were created:" \n <( \N* } for lines.join: "\n";'  file

#OR

~$ raku -e 'put $0.words[1] if m{ "Artifacts were created:" \n (\N*) } for lines.join: "\n";'  file  

OP가 Perl 프로그래밍 언어 제품군을 기꺼이 고려한다면 Raku가 좋은 선택입니다. 위에서는 입력 파일을 한 줄씩 읽고 \n개행 문자로 연결합니다. 대상을 식별한 "Artifacts were created:" \n다음 일치하는 항목을 찾습니다.

첫 번째 예에서 Raku의 캡처 태그는 <( … )>일치 개체에서 "Artifacts..." 줄을 제거하는 데 사용되며, .words[1]캡처된 두 번째 공백으로 구분된 필드는 일치 변수와 함께 사용 (또는 동의어 ) put됩니다 ( 조건부 출력 에 따라 다름 ). . 실제로 이 문제에는 캡처 태그가 하나만 필요합니다 .$<>$/if<(

두 번째 예에서는 괄호를 사용하여 일치 항목의 일부를 $<>.[0]match-variable 과 동일한 $/.[0]match-variable 로 캡처합니다 $0. 캡처된 .words[1]두 번째 공백으로 구분된 필드 $0에는 조건이 put적용 됩니다 if.

입력 예:

10:28:48  2022-09-15T15:28:36Z:    Creating tar ball for build artifacts
--
10:28:53  --> Build complete: Artifacts were created:
file: build-1.tar.gz

예제 출력:

build-1.tar.gz

Raku에는 실제로 꽤 많은 내장 문자 클래스가 있으므로 [\N* \n]특징적인 패턴(0개 이상의 비개행 문자 다음에 개행 문자가 오는 것)을 다른 많은 패턴(예: [\S* \s]또는 [\d* \D]등)에 복사할 수 있습니다.

https://docs.raku.org/언어/regexes
https://raku.org

관련 정보