GNU/Linux >> Tutoriels Linux >  >> Linux

Comment appeler une fonction Bash dans le script Bash à l'intérieur d'Awk ?

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

Linux
  1. Comment déboguer un script bash ?

  2. Comment définir les paramètres lorsque Pipe Bash Script to Bash ?

  3. Comment diviser une chaîne dans un script bash

  4. Comment créer et appeler des fonctions dans Bash

  5. Bash Script - Comment lire l'entrée de l'utilisateur

Comment exécuter un script bash {7 méthodes}

Fonction Bash et comment l'utiliser {Variables, Arguments, Return}

Comment écrire un script bash avec des exemples

Comment exécuter un script bash

Comment utiliser Linux Bash Shell dans Windows 10 ?

Comment vérifier la syntaxe d'un script Bash sans l'exécuter ?