awk에서 사용자 정의 bash 함수 사용

awk에서 사용자 정의 bash 함수 사용

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해야 합니다 .awkbashbashawk

사소한 것이 아닙니다.

bash후속 호출에서 사용할 수 있도록 환경을 통해 함수를 내보내는 기능이 지원되므로 이는 호출자 bash에게 함수 정의를 전달하는 한 가지 방법입니다 .bashawk

export -f d2h

awk(여기서) 명령을 실행하는 유일한 방법은 해당 , 또는 bash을 사용하는 것입니다 . 모든 경우에 셸은 이를 해석하기 위해 실행되지만 대신 가 됩니다 . 따라서 함수를 호출하기 위해 명령줄을 해석하는 호출 인 명령줄을 작성해야 하므로 인용에 주의해야 합니다.system("cmd")print... | "cmd""cmd" | getlineawkcmdshbashshbashbash

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

관련 정보