Bash 스크립트에서 여러 줄을 파이프하십시오.

Bash 스크립트에서 여러 줄을 파이프하십시오.

구문 분석해야 하는 복잡한 로그가 있습니다. 내가 원하는 것은 문자열을 찾는 것입니다시간, 일치하는 행에서 열 5를 가져온 다음 열 5가 문자열과 일치하는 다른 모든 행을 가져옵니다.시간.

입력 예

a b c d 31 1
a b c d 31 H
a b c d 31 2
a b c d 32 1
a b d d 32 2
a b c d 33 1
a b c d 33 H
a b c d 33 2

예상 출력

a b c d 31 1
a b c d 31 H
a b c d 31 2
a b c d 33 1
a b c d 33 H
a b c d 33 2

따라서 두 개의 별도 스크립트를 만들어 이 작업을 수행할 수 있습니다. script1 | xargs -n1 | script2

스크립트 1검색 문자열시간를 누른 다음 다섯 번째 열을 인쇄합니다.
cat logfile | grep 'H' | awk '{print $5}'

스크립트 2그런 다음 열 5가 첫 번째 스크립트의 출력과 일치하는 로그 파일의 다른 모든 줄을 인쇄합니다. cat logfile | awk -v var="$1" '$5 == var'

입력 파일, 로그 파일을 변수로 만들어 스크립트에서 $1을 사용한 다음 script logfile. 일반적으로 이를 수행하는 올바른 방법은 무엇입니까? 나는 bash 스크립팅을 처음 접했기 때문에 평균이라고 말합니다.

내가 가진 두 가지 문제는 첫째, 첫 번째 스크립트(즉, 로그 파일)의 $1이 내가 awk로 파이프하는 두 번째 스크립트(즉, 첫 번째 스크립트의 출력 번호)의 $1과 다릅니다. 둘째, xargs -n1bash 스크립트에서 사용할 수 있는 해당 항목을 찾을 수 없습니다 .

답변1

두 번째는 awk두 개의 입력을 차례로 읽습니다. 첫 번째에서 파이프된 출력을 읽은 다음 awk파일 자체에서 파이프된 출력을 읽습니다. 두 번째 입력의 시작을 식별하는 한 가지 방법은 NR(질소현재 투입량오른쪽전체 기록)이 더 이상 일치하지 않습니다 FNR(현재에프ile의 레코드 번호). -FILE arg는 awk슬레이브에게 stdin(를 통해) 알리는 것을 의미합니다.관로, 이 경우).

awk '$6=="H"{print $5}' "$1" |
awk 'NR==FNR{k[$1];next}
     $5 in k{print}' - "$1"

두 번째 입력을 식별하는 위의 방법은 일반적으로 사용되지만 첫 번째 입력에서 아무것도 읽지 않으면 예상/원하는 대로 동작하지 않습니다. 이 작업의 요구 사항의 경우 첫 번째 입력이 아무것도 제공하지 않아도 상관 없습니다. 논리는 인덱스 값 목록을 NR=FNR작성하는 곳(예: 기본 파일에서)을 결코 지나치지 않지만 이를 사용하여 아무 작업도 수행하지 않습니다. 따라서 스크립트는 빈 입력으로 파이프되지만 이는 단지 혼란 때문입니다. 특정 논리가 부작용으로 사용됩니다.k$1

gawk그러나 GNU awk()에는 현재 파일/파이프를 결정하는 안정적인 방법이 있습니다 . 명령줄 인수에는 특별한 변형이 있습니다 FILE:"...var=value 형식의 인수는 var 변수에 값을 할당합니다. 이는 파일을 전혀 지정하지 않습니다."- 바라보다:기타 명령줄 매개변수 이러한 배치변수=값args가 중요합니다 - 특정 파일에 필요한 값은 명령줄에 배치되어야 합니다앞으로관련 파일 – 후속 조치변수=값awk이전 파일/파이프를 완전히 읽을 때까지 적용되지 않습니다.

여기있어변수=값버전.

gawk '$6=="H"{print $5}' "$1" |
gawk 'fn==1{k[$1];next}
      $5 in k{print}' fn=1 - fn=2 "$1"

출력(두 스크립트 버전 모두 동일)

a b c d 31 1
a b c d 31 H
a b c d 31 2
a b c d 33 1
a b c d 33 H
a b c d 33 2

관련 정보