AWK 내부에서 bash 쉘 기능 사용

어떻게 든 AWK 내부에서 bash 기능을 사용할 수 있습니까?

예제 파일 (string, int, int) , int)

Mike 247808 247809 247810 

10 진수에서 16 진수로 값을 변환하려고합니다.

.bashrc 또는 셸 스크립트

$ awk "{print $1 ; d2h($2)}" file awk: calling undefined function d2h input record number 1, file file source line number 1 

답변

system() 함수 사용 :

awk "{printf("%s ",$1); system("d2h " $2)}" file 

귀하의 경우 systemd2h 247808를 호출 한 다음이 명령의 출력을 printf 출력에 추가합니다.

Mike 3C800 

수정 :

systembashsh를 사용합니다. / div> .bashrc에 액세스하는 방법을 찾을 수 없습니다.하지만 현재 bash 스크립트의 함수를 계속 사용할 수 있습니다.

#!/bin/bash d2h() { # do some cool conversion here echo "$1" # or just output the first parameter } export -f d2h awk "{printf("%s ",$1); system("bash -c "\""d2h "$2""\""")}" file 

편집 2 :

모름 왜, 그러나 이것은 내 Ubuntu 16.04에서 작동하지 않습니다. 우분투 14.04에서 작동했기 때문에 이상합니다.

댓글

  • d2h는 실행 파일이지만 ‘ ” 함수가 .bashrc 또는 쉘 스크립트에 정의 된 경우 “.
  • @MichaelHomer 예, 맞습니다. 귀하의 의견 덕분에 나는 아무도 묻지 않은 질문에 대답했다는 것을 깨달았습니다. 하지만 현재 스크립트 (그리고 source를 통해 다른 스크립트에서 가능)의 함수를 사용하는 방법을 찾았지만 ‘ f figure ‘ .bashrc에서 작동하지 않는 이유를 설명합니다.
  • 그 ‘는 $2의 내용이 결국 셸 코드로 해석되기 때문에 명령 주입 취약점이기도합니다.
  • If export -f d2h 작동하지 않음 ‘ ksh / zsh에 대해 다음과 같이 할 수 있습니다. (\ 42 및 \ 47은 간단한 큰 따옴표와 큰 따옴표의 이스케이프 코드입니다.) CODE=$(typeset -f d2h) awk ' { system("bash -c \47eval \42$CODE\42; d2h \42"$2"\42\47") }'

Answer

awk에서 bash를 호출하고 출력을 사용할 수 있습니다. 너무 자주 발생하면 성능 측면에서 분명히 위험합니다. 맨 페이지 인용 :

command | getline [var] 

출력을 $ 0 또는 var로 파이핑하는 명령을 실행합니다.

명령은 함수 정의를 포함하고 함수를 실행하는 bash 스크립트입니다.

답변

10 진수에서 16 진수로 변환하는 것은 awk 자체적으로 잘 수행 할 수있는 작업입니다. 그리고이를 위해 awk 함수를 정의 할 수 있습니다.

 function d2h(d) { return sprintf("%x", d) }  

이제 일반적인 경우의 질문에 답하기 위해 awkbash 함수의 경우 bash 셸을 실행하려면 awk가 필요합니다. bash 해당 함수의 정의를 해석하고 awk에서 추출한 값을 인수로 전달하여 해당 함수를 호출합니다.

사소하지 않습니다.

bash는 환경을 통한 함수 내보내기를 지원하므로 bash의 후속 호출에서 사용할 수 있습니다. awk에 의해 호출 된 bash에 대한 함수 정의 :

export -f d2h 

awk가 명령을 실행하는 유일한 방법 (bash h ere)는 system("cmd") 또는 print... | "cmd" 또는 "cmd" | getline에 있습니다. 모든 경우에 awk는 셸을 실행하여 cmd를 해석하지만 sh, bash가 아닙니다. 따라서 bash을 해석하는 bash 호출 인 sh에 대한 명령 줄을 구성해야합니다. div> 명령 줄을 사용하여 함수를 호출하므로 인용에주의해야합니다.

export -f d2h <file awk -v q=""" " function shquote(s) { gsub(q, q "\\" q q, s) return q s q } {print $1; system("exec bash -c "\""d2h \"$1\""\"" bash " shquote($2))}" 

함수 출력을 awk, 파이프를 통해 다시 전송해야합니다.이를 위해 iv id = “대신 cmd | getline를 사용합니다. 4be2d082e4 “>

(cmd“의 표준 출력은 그대로 둡니다).

cmd | getline line 한 줄 을 저장합니다 (엄격히 말하면 하나의 레코드 , 레코드는 기본적으로 줄임). 여러 줄로 구성된 경우 전체 출력을 얻으려면 다음과 같은 루프가 필요합니다.

 awk "... cmd = "exec bash -c "\""d2h \"$1\""\"" bash " shquote($2) output = "" while ((cmd | getline line) > 0) { output = output line RS } sub(RS "$", "", output) # remove the last newline ..."  

즉, 각 함수 호출에 대해 sh 하나와 bash 하나를 실행하는 것입니다. , 매우 비효율적입니다. 이는 bashwhile read loop를 사용하여 읽고 분할하는 것보다 훨씬 더 비효율적입니다.

(unset -v IFS; while read -r a b rest; do printf "%s\n" "$a" d2h "$b" done < file) 

또한 shellshock 이후 bash는 이제 BASH_FUNC_d2h%%와 같은 이름의 환경 변수에서 함수를 내 보냅니다. div>. mksh 및 최신 버전의 dash 제거 em를 포함한 일부 sh 구현 > 환경에서 가져온 환경 변수 :

$ env "foo%%=bar" dash -c "printenv foo%%" $ env "foo%%=bar" mksh -c "printenv foo%%" $ env "foo%%=bar" zsh -c "printenv foo%%" bar $ env "foo%%=bar" bash -c "printenv foo%%" bar 

따라서 간단한 함수 내보내기 기능에 의존하는 대신 다른 방법으로 함수 정의를 전달할 수 있습니다. 일반적인 이름의 환경 변수를 통해 가능합니다.

 BASH_FUNCTIONS=$(typeset -f d2h) awk " ... cmd = "exec bash -c "\""eval \"$BASH_FUNCTIONS\";" \ "d2h \"$1\""\"" bash " shquote($2) ..."  

답변

해보기 :

awk "{print $1 ; printf "%x\n", $2}" file 

AFAIK, bash를 사용할 수 없습니다. awk의 함수이지만 스크립트 만 있습니다. 필요한 경우 awk 함수를 사용할 수 있습니다.

Answer

사용자 정의 bash 함수 사용 inside awk

면책 조항 : 이것이 OP가하려는 것이 아니라는 것을 알고 있지만 Google은 나와 같은 다른 사람들을이 답변으로 안내 할 것입니다.

상황

함수로 구성된 bash 스크립트가 있으며 (자신이나 [대부분의] 동료를 미워하지 않기 때문에) 이러한 기능 중 적어도 하나는 awk 내에서 다른 사람에게 전화를 겁니다.

솔루션

스크립트

#!/bin/env bash # The main function - it"s a sound pattern even in BASH main(){ # In the awk command I do some tricky things with single quotes. Count carefully... # The first $0 is outside the single quotes so it is the name of the current bash script. # The second $0 is inside the single quotes so it is awk"s current line of input. awk "{printf("%s. ", ++c); system(""$0" --do"); print $0}"<<-PRETEND_THIS_IS_AN_INPUT_STREAM and and well PRETEND_THIS_IS_AN_INPUT_STREAM } # functionized to keep things DRY doit(){ echo -n "doin" it " } # check for a command switch and call different functionality if it is found if [[ $# -eq 1 && $1 == "--do" ]]; then doit else main fi 

출력

$ ./example.sh 1. doin" it and 2. doin" it and 3. doin" it well 

댓글

  • I Queens를 대표합니다. 그녀는 Brooklyn에서 자랐습니다.

Answer

@HaukeLaging “s를 보여주는 간단한 예입니다. command|getline :

  1. 입력 :
Dear friends my name is `id -nu` and today is `date "+%Y-%m-%d"`. 

입력에서 셸 구문을 따르는 경우

`command` 

인라인 명령 이 결과로 대체됨을 나타내는 데 사용됩니다.

  1. 다음 방법으로 인라인 셸 명령을 확장 할 수 있습니다.
#!/usr/bin/gawk -f BEGIN { FS ="`"; } NF==3 { $2 | getline $2 } { print } 
  1. 사용법 (일반적인 chmod 이후) :
$ expand-inline input Dear friends my name is jjoao and today is 2018-01-15. 

답변

이렇게하면 좋은 기회를 얻을 수 있습니다.

cat ../logs/em2.log.1 |grep -i 192.168.21.15 |awk "{system("date"); print $1}" 

시스템 기능을 사용하면 awk 스트림 내에서 bash 명령을 구문 분석 할 수 있습니다.

Answer

GNU awk의 경우이 답변이지만 다른 버전에서도 동일한 트릭을 구현할 수 있습니다. 아이디어는 파이프의 오른쪽이 정확히 동일하고 “종료되지 않는 한”awk는 파이프를 닫지 않는다는 것입니다. 그러나 다른 경우 새 파이프가 열립니다. 예를 들어 다음을 입력하는 경우 :

awk "BEGIN{ shell= "/bin/bash" } { print $0 | "/bin/bash" } END { print "echo $a" | " /bin/bash" }" 

다음을 입력 할 수 있습니다.

a=5 echo $a 

및 예상 (?) 응답을 얻습니다. 5 : 새 셸이 생성되지 않았습니다. 그러나 END 섹션에서 추가 공백을 입력했기 때문에 파이프의 RHS가 다르고 변수 a에 대한 값이없는 새 쉘이 생성됩니다 (따라서 종료시 빈 줄을 인쇄합니다. 그러나 장기 파이프를 사용하는 권장 방법은 내가 가진 것과 같습니다. 명령을 변수의 BEGIN 섹션에 넣고 해당 변수를 재사용합니다.

사용자 정의 함수를 bash 세션에 제공하고 재사용은 독자에게 맡겨진 연습입니다 🙂

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다