Tento problém souvisí s používáním funkce bash shell uvnitř AWK
Mám tento kód
#!/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
a mám tento soubor:
cat smile happy laugh
dog angry sad
mouse happy
wolf sad cry
fox sleep quiet
Výstup by měl vypadat takto:
smile
happy
laugh
angry
sad
happy
sad
cry
sleep
quiet
Problém, který mi říká bash: emotion: command not found
Podle komentáře akarilimana zde
toto nefunguje na mém Ubuntu 16.04. To je zvláštní, protože to dříve fungovalo „na Ubuntu 14.04.
Jak to tedy udělat v novějších verzích?
Přijatá odpověď:
To pravděpodobně není nejlepší způsob, jak k problému přistupovat.
Z awk , vše, co můžete udělat, je vytvořit příkazový řádek, který system() přechází na sh . Takže potřebujete, aby byly argumenty formátovány v sh syntaxe.
Takže budete potřebovat:
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)
}'
Zde cituji $1 awk takže jej lze bezpečně vložit do sh příkazový řádek, který skončí spuštěním bash s obsahem $1 jako poslední argument, který jej poté předá emotion .
To předpokládá vaše sh a vaše awk neodstraňujte speciální proměnné prostředí, které bash používá k exportu funkcí (jako pdksh a deriváty (například mksh ) například nebo dash od 0.5.8, což vysvětluje váš problém 14.04 vs 16.04), a že vaše distribuce nezakázala exportované funkce v bash .
Pokud ano, můžete to udělat jako pro ksh /zsh a předejte definici funkce jiným způsobem, například:
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)
}'
V obou případech to znamená spustit jeden sh a jeden bash. Možná můžete předat $i na bash nějakým jiným způsobem než přes system() který pokaždé provede dvě instance shellu. Jako:
awk '{for (i=2; i<=NF; i++) printf "%s\0" $i}' |
while IFS= read -r i; do
emotion "$i"
done
Nebo proveďte rozdělení slov v bash přímo:
unset IFS
while read -ra fields; do
for i in "${fields[@]:1}"; do
emotion "$i"
done
done