GNU/Linux >> Linux の 問題 >  >> Linux

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のコメントによると

これは私のUbuntu16.04では機能しません。以前は「Ubuntu14.04で」動作していたため、これは奇妙なことです。

では、新しいバージョンでそれを行う方法は?

承認された回答:

それはおそらく問題に取り組むための最良の方法ではありません。

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 \"[email protected]\"'\'' bash " sh_quote($1)
  }'

ここでawkの$1を引用します そのため、shに安全に埋め込むことができます 最終的にbashを実行するコマンドライン $1の内容で 最後の引数として、それをemotionに渡します 。

それはあなたのshを前提としています そしてあなたのawk bashする特別な環境変数を削除しないでください 関数のエクスポートに使用します(pdkshなど) および派生物(mkshなど) )たとえば、またはdash 14.04と16.04の問題を説明する0.5.8以降)、およびディストリビューションがbashでエクスポートされた関数を無効にしていないこと 。

もしそうなら、あなたはkshのようにそれをすることができます / 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 \"[email protected]\"'\'' bash " \
                      sh_quote($1)
  }'

どちらの場合も、それは1つのshと1つのbashを実行することを意味します。たぶんあなたは$iを渡すことができます bashsystem()以外の方法 毎回シェルの2つのインスタンスを実行します。いいね:

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

Linux
  1. Bashスクリプトをデバッグする方法は?

  2. BashスクリプトをBashにパイプするときにパラメータを設定する方法は?

  3. Bash で関数を作成して呼び出す方法

  1. Bash スクリプト - ユーザー入力の読み取り方法

  2. VimでBashスクリプトを強調表示するには?

  3. パラメータをBashスクリプトに渡す方法は?

  1. Bashでは、いつエイリアスを作成し、いつスクリプトを作成し、いつ関数を作成するのですか?

  2. サブルーチンのように他のシェルスクリプトを呼び出す方法は?

  3. Bashスクリプトで文字列を分割する方法