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
인용할 수 있습니다 . 여기서는 파일을 탐색할 때 최신 항목을 캡처하는 보다 직접적인 접근 방식을 선호합니다.$2
END
업데이트된 요구 사항에서는 일치 항목 바로 다음 행에 값을 제공해야 합니다. 파일을 완전히 처리할 필요가 없기 때문에 이는 훨씬 더 간단하고 더 빠릅니다.
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]
등)에 복사할 수 있습니다.