awk 내부의 bash 스크립트에서 bash 함수를 호출하는 방법은 무엇입니까?

awk 내부의 bash 스크립트에서 bash 함수를 호출하는 방법은 무엇입니까?

이 질문에는 다음이 포함됩니다.AWK에서 bash 쉘 기능 사용

이 코드가 있습니다

#!/bin/bash

function emotion() {
            #here is function code end with return value...
            echo $1
}

export -f emotion

#I've put all animals in array
animalList=($(awk '{print $1}' animal.csv)) 

#loop  array and grep all the lines form the file
for j in ${animalList[@]}
do
  :                                                     #here I'am running a bash script calling emotion function 
   grep $j animal.csv | awk '{for(i=2;i<=NF;i++){system("bash -c '\''emotion "$i"'\''")}}'
done

나는 이 파일을 가지고 있습니다 :

cat    smile    happy   laugh
dog    angry    sad
mouse  happy    
wolf   sad      cry
fox    sleep    quiet 

출력은 다음과 같아야 합니다.

smile
happy
laugh
angry
sad
happy    
sad
cry
sleep
quiet 

그것은 나에게 문제를 말해준다bash: emotion: command not found

akarilimano의 의견을 바탕으로여기

Ubuntu 16.04에서는 작동하지 않습니다. "Ubuntu 14.04에서 실행"되었기 때문에 이것은 이상합니다.

그렇다면 새 버전에서는 어떻게 해야 할까요?

답변1

이는 문제를 해결하는 최선의 방법이 아닐 수도 있습니다.

에서 awk할 수 있는 일은 system()에 전달되는 명령줄을 작성하는 것뿐입니다 sh. 따라서 구문에서 매개변수의 형식을 지정해야 합니다 sh.

따라서 다음이 필요합니다.

emotion() {
  echo "$i"
}
export -f emotion
awk -v q="'" '
  function sh_quote(s) {
    gsub(q, q "\\" q q, s)
    return q s q
  }
  {
    for (i = 2; i <= NF; i++)
      status = system("bash -c '\''emotion \"$@\"'\'' bash " sh_quote($1)
  }'

awk는 명령줄에 안전하게 내장되어 궁극적으로 마지막 인수의 내용으로 실행될 $1수 있도록 여기에서 참조되며 , 이 내용은 .shbash$1emotion

귀하 sh와 귀하가 함수(예: 및 파생물(예: )) 를 내보내는 데 사용되는 특수 환경 변수를 awk제거하지 않는다고 가정하면,bashpdkshmksh또는 dash14.04와 16.04 문제를 설명하는 0.5.8부터 시작합니다.) 배포판이 이를 비활성화하지 않았습니다 bash.

그렇다면 kshfor/처럼 수행 zsh하고 다음과 같이 함수 정의를 다른 방법으로 전달할 수 있습니다.

CODE=$(typeset -f emotion) awk -v q="'" '
  function sh_quote(s) {
    gsub(q, q "\\" q q, s)
    return q s q
  }
  {
    for (i = 2; i <= NF; i++)
      status = system("bash -c '\''eval \"$CODE\"; emotion \"$@\"'\'' bash " \
                      sh_quote($1)
  }'

두 경우 모두 이는 sh와 bash를 실행하는 것을 의미합니다. 매번 두 개의 쉘 인스턴스를 전달하는 것 외에 다른 방법을 $i전달할 수도 있습니다 . 좋다:bashsystem()

awk '{for (i=2; i<=NF; i++) printf "%s\0" $i}' |
  while IFS= read -r i; do
    emotion "$i"
  done

또는 단어 분할을 직접 수행합니다 bash.

unset IFS
while read -ra fields; do
  for i in "${fields[@]:1}"; do
    emotion "$i"
  done
done

답변2

귀하의 스크립트는 셸 /bin/sh에 연결되어 있기 때문에 Ubuntu 16.04에서는 작동하지 않지만 Ubuntu 14.04에서는 셸 에 연결됩니다 . 이것이 왜 중요합니까? Awk의 기능은 Ubuntu 16.04에서 쉘을 사용 하고 호출합니다 .dash/bin/shbashsystem()/bin/shdash

관련 정보