この質問には以下が含まれます。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
ようにここで参照されます。sh
bash
$1
emotion
あなたsh
とあなたが関数(例えば、派生物(例えば))をエクスポートするために使用される特別な環境変数を削除しないと仮定するawk
と、bash
pdksh
mksh
または、dash
14.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
できます。良い:bash
system()
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/sh
bash
system()
/bin/sh
dash