AWK에서 bash 기능을 사용할 수 있습니까?
샘플 파일(문자열, 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
답변1
다음 기능을 사용해 보세요 system()
.
awk '{printf("%s ",$1); system("d2h " $2)}' file
귀하의 경우 명령의 출력이 system
호출된 d2h 247808
다음 printf
출력에 추가됩니다.
Mike 3C800
편집하다:
system
대신 에 나는 그것에 접근하는 방법을 찾을 수 sh
없습니다 . 하지만 현재 bash 스크립트의 기능을 계속 사용할 수 있습니다.bash
.bashrc
#!/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
참고: -f
다음 용도로 사용됨함수 내보내기변수보다는요.
편집 2:
이유는 모르겠지만 Ubuntu 16.04에서는 작동하지 않습니다. Ubuntu 14.04에서 실행되었기 때문에 이것은 이상합니다.
답변2
awk에서 bash를 호출하고 해당 출력을 사용할 수 있습니다. 성능 관점에서 볼 때 이러한 일이 너무 자주 발생하면 분명히 위험합니다. 매뉴얼 페이지를 인용하면 다음과 같습니다.
command | getline [var]
명령을 실행하여 출력을 $0 또는 var로 파이프합니다.
명령은 함수 정의를 포함하고 해당 함수를 실행하는 bash 스크립트입니다.
답변3
10진수에서 16진수로의 변환은 awk
그 자체로 잘 수행될 수 있습니다. 다음을 정의할 수 있습니다.awk
이 작업을 수행하는 함수:
function d2h(d) {
return sprintf("%x", d)
}
awk
이제 일반적인 질문에 답하려면, 함수를 실행 하려면 함수의 정의를 해석하고 추출된 값을 인수로 전달하는 함수를 호출하는 셸을 실행 bash
해야 합니다 .awk
bash
bash
awk
사소한 것이 아닙니다.
bash
후속 호출에서 사용할 수 있도록 환경을 통해 함수를 내보내는 기능이 지원되므로 이는 호출자 bash
에게 함수 정의를 전달하는 한 가지 방법입니다 .bash
awk
export -f d2h
awk
(여기서) 명령을 실행하는 유일한 방법은 해당 , 또는 bash
을 사용하는 것입니다 . 모든 경우에 셸은 이를 해석하기 위해 실행되지만 대신 가 됩니다 . 따라서 함수를 호출하기 위해 명령줄을 해석하는 호출 인 명령줄을 작성해야 하므로 인용에 주의해야 합니다.system("cmd")
print... | "cmd"
"cmd" | getline
awk
cmd
sh
bash
sh
bash
bash
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
다시 파이프해야 합니다. 이를 수행하려면 cmd | getline
대신 사용할 수 있습니다 system(cmd)
( 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)
bash
또한 Shellshock 함수는 이제 이라는 환경 변수로 내보내지기 때문에 참고하세요 BASH_FUNC_d2h%%
. 일부 sh
구현에는 mksh
최신 버전이 포함됩니다.dash
제거하다환경의 해당 환경 변수는 다음과 같습니다.
$ 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)
...'
답변4
awk에서 사용자 정의 bash 함수 사용
부인 성명:나는 이것이 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