
어떻게 든 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
방법을 찾을 수 없습니다 .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
참고: 다음과 -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
파이프를 통해 다시 전송해야 합니다. 이를 위해서는 (의 stdout을 그대로 유지하는) 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)
또한 Shellshock 이후로 bash
이제 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