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

そのksh場合は for/ のように実行し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を実行することを意味します。毎回2つのシェルインスタンスを渡すことに加えて、他の方法を渡すことも$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

関連情報