어떻게 든 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
귀하의 경우 system
는 d2h 247808
를 호출 한 다음이 명령의 출력을 printf
출력에 추가합니다.
Mike 3C800
수정 :
system
는 bash
sh를 사용합니다. / 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에서 작동했기 때문에 이상합니다.
댓글
Answer
awk에서 bash를 호출하고 출력을 사용할 수 있습니다. 너무 자주 발생하면 성능 측면에서 분명히 위험합니다. 맨 페이지 인용 :
command | getline [var]
출력을 $ 0 또는 var로 파이핑하는 명령을 실행합니다.
명령은 함수 정의를 포함하고 함수를 실행하는 bash 스크립트입니다.
답변
10 진수에서 16 진수로 변환하는 것은 awk
자체적으로 잘 수행 할 수있는 작업입니다. 그리고이를 위해 awk
함수를 정의 할 수 있습니다.
function d2h(d) { return sprintf("%x", d) }
이제 일반적인 경우의 질문에 답하기 위해 awk
가 bash
함수의 경우 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
하나를 실행하는 것입니다. , 매우 비효율적입니다. 이는 bash
가 while 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
:
- 입력 :
Dear friends my name is `id -nu` and today is `date "+%Y-%m-%d"`.
입력에서 셸 구문을 따르는 경우
`command`
는 인라인 명령 이 결과로 대체됨을 나타내는 데 사용됩니다.
- 다음 방법으로 인라인 셸 명령을 확장 할 수 있습니다.
#!/usr/bin/gawk -f BEGIN { FS ="`"; } NF==3 { $2 | getline $2 } { print }
- 사용법 (일반적인 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 세션에 제공하고 재사용은 독자에게 맡겨진 연습입니다 🙂
d2h
는 실행 파일이지만 ‘ ” 함수가 .bashrc 또는 쉘 스크립트에 정의 된 경우 “.source
를 통해 다른 스크립트에서 가능)의 함수를 사용하는 방법을 찾았지만 ‘ f figure ‘.bashrc
에서 작동하지 않는 이유를 설명합니다.$2
의 내용이 결국 셸 코드로 해석되기 때문에 명령 주입 취약점이기도합니다.export -f d2h
작동하지 않음 ‘ ksh / zsh에 대해 다음과 같이 할 수 있습니다. (\ 42 및 \ 47은 간단한 큰 따옴표와 큰 따옴표의 이스케이프 코드입니다.)CODE=$(typeset -f d2h) awk ' { system("bash -c \47eval \42$CODE\42; d2h \42"$2"\42\47") }'