Ce problème est lié à l'utilisation de la fonction shell bash dans AWK
J'ai ce code
#!/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
et j'ai ce fichier :
cat smile happy laugh
dog angry sad
mouse happy
wolf sad cry
fox sleep quiet
Le résultat devrait ressembler à ceci :
smile
happy
laugh
angry
sad
happy
sad
cry
sleep
quiet
Le problème, il me dit bash: emotion: command not found
D'après le commentaire d'akarilimano ici
cela ne fonctionne pas sur mon Ubuntu 16.04. C'est étrange, car cela fonctionnait "sur Ubuntu 14.04.
Alors, comment faire dans les nouvelles versions ?
Réponse acceptée :
Ce n'est probablement pas la meilleure façon d'aborder le problème.
De awk
, tout ce que vous pouvez faire est de créer une ligne de commande qui system()
passe à sh
. Donc, vous avez besoin que les arguments soient formatés dans le sh
syntaxe.
Il vous faudrait donc :
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)
}'
Citant ici le $1
d'awk afin qu'il puisse être intégré en toute sécurité dans le sh
ligne de commande qui finit par exécuter bash
avec le contenu de $1
comme dernier argument, qui le passe ensuite à emotion
.
Cela suppose que votre sh
et votre awk
ne supprimez pas les variables d'environnement spéciales qui bash
utilise pour exporter des fonctions (comme pdksh
et dérivés (tels que mksh
) faire par exemple, ou dash
depuis 0.5.8, ce qui explique votre problème 14.04 vs 16.04), et que votre distribution n'a pas désactivé les fonctions exportées dans bash
.
Si c'est le cas, vous pouvez le faire comme pour ksh
/zsh
, et passez la définition de la fonction d'une autre manière, comme :
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)
}'
Dans les deux cas, cela signifie exécuter un sh et un bash pour cela. Peut-être que vous pouvez passer le $i
pour bash
autrement que via un system()
qui exécute deux instances d'un shell à chaque fois. Comme :
awk '{for (i=2; i<=NF; i++) printf "%s\0" $i}' |
while IFS= read -r i; do
emotion "$i"
done
Ou faites le fractionnement de mots dans bash
directement :
unset IFS
while read -ra fields; do
for i in "${fields[@]:1}"; do
emotion "$i"
done
done