GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cómo llamar a una función Bash en Bash Script dentro de Awk?

Este problema está relacionado con el uso de la función bash shell dentro de AWK

Tengo este código

#!/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

y tengo este archivo:

cat    smile    happy   laugh
dog    angry    sad
mouse  happy    
wolf   sad      cry
fox    sleep    quiet 

La salida debería ser así:

smile
happy
laugh
angry
sad
happy    
sad
cry
sleep
quiet 

El problema me dice bash: emotion: command not found

Según el comentario de akarilimano aquí

esto no funciona en mi Ubuntu 16.04. Esto es extraño, porque solía funcionar “en Ubuntu 14.04.

Entonces, ¿cómo hacerlo en las versiones más nuevas?

Respuesta aceptada:

Probablemente esa no sea la mejor manera de abordar el problema.

Desde awk , todo lo que puede hacer es construir una línea de comando que system() pasa a sh . Entonces, necesita que los argumentos estén formateados en el sh sintaxis.

Así que necesitarías:

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)
  }'

Aquí citando $1 de awk para que se pueda incrustar de forma segura en el sh línea de comando que termina ejecutando bash con el contenido de $1 como último argumento, que luego lo pasa a emotion .

Eso asume su sh y tu awk no elimine las variables de entorno especiales que bash utiliza para exportar funciones (como pdksh y derivados (como mksh ) hacer por ejemplo, o dash desde 0.5.8, lo que explica su problema de 14.04 frente a 16.04), y que su distribución no ha deshabilitado las funciones exportadas en bash .

Si es así, podrías hacerlo como para ksh /zsh y pasar la definición de la función de otra forma, como:

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)
  }'

En ambos casos, eso significa ejecutar un sh y un bash para ello. Tal vez puedas pasar el $i a bash de otra manera que no sea a través de un system() que ejecuta dos instancias de un shell cada vez. Me gusta:

awk '{for (i=2; i<=NF; i++) printf "%s\0" $i}' |
  while IFS= read -r i; do
    emotion "$i"
  done

O haz la división de palabras en bash directamente:

unset IFS
while read -ra fields; do
  for i in "${fields[@]:1}"; do
    emotion "$i"
  done
done

Linux
  1. En Bash, ¿cuándo alias, cuándo escribir y cuándo escribir una función?

  2. ¿Cómo llamar a otro script de Shell como una subrutina?

  3. Cómo crear y llamar funciones en Bash

  4. Bash Script - Cómo leer la entrada del usuario

  5. Cómo llamar a la función C en C++, función C++ en C (Mezclar C y C++)

Cómo ejecutar un script Bash {7 métodos}

Función Bash y cómo usarla {Variables, Argumentos, Retorno}

Cómo escribir un script Bash con ejemplos

Cómo ejecutar un script Bash

¿Cómo usar Linux Bash Shell dentro de Windows 10?

¿Cómo verifico la sintaxis de un script Bash sin ejecutarlo?