Questo problema è correlato all'utilizzo della funzione della shell bash all'interno di AWK
Ho questo codice
#!/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
e ho questo file:
cat smile happy laugh
dog angry sad
mouse happy
wolf sad cry
fox sleep quiet
L'output dovrebbe essere simile a questo:
smile
happy
laugh
angry
sad
happy
sad
cry
sleep
quiet
Il problema mi dice bash: emotion: command not found
Secondo il commento di akarilimano qui
questo non funziona sul mio Ubuntu 16.04. Questo è strano, perché prima funzionava “su Ubuntu 14.04.
Quindi come farlo nelle versioni più recenti?
Risposta accettata:
Probabilmente non è il modo migliore per affrontare il problema.
Da awk
, tutto ciò che puoi fare è creare una riga di comando che system()
passa a sh
. Quindi, hai bisogno che gli argomenti siano formattati in sh
sintassi.
Quindi avresti bisogno di:
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)
}'
Qui citando $1
di awk quindi può essere tranquillamente incorporato nel sh
riga di comando che finisce per eseguire bash
con il contenuto di $1
come ultimo argomento, che poi lo passa a emotion
.
Ciò presuppone il tuo sh
e il tuo awk
non rimuovere le variabili di ambiente speciali che bash
utilizza per esportare funzioni (come pdksh
e derivati (come mksh
) per esempio, o dash
dalla 0.5.8 che spiega il tuo problema 14.04 vs 16.04) e che la tua distribuzione non ha disabilitato le funzioni esportate in bash
.
Se lo fa, potresti farlo come per ksh
/zsh
, e passare la definizione della funzione in un altro modo, ad esempio:
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)
}'
In entrambi i casi, ciò significa eseguire una sh e una bash per questo. Forse puoi passare il $i
per bash
in un altro modo che tramite un system()
che esegue due istanze di una shell ogni volta. Come:
awk '{for (i=2; i<=NF; i++) printf "%s\0" $i}' |
while IFS= read -r i; do
emotion "$i"
done
Oppure fai la divisione delle parole in bash
direttamente:
unset IFS
while read -ra fields; do
for i in "${fields[@]:1}"; do
emotion "$i"
done
done