Dieses Problem steht im Zusammenhang mit der Verwendung der Bash-Shell-Funktion in AWK
Ich habe diesen 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
und ich habe diese Datei:
cat smile happy laugh
dog angry sad
mouse happy
wolf sad cry
fox sleep quiet
Die Ausgabe sollte so aussehen:
smile
happy
laugh
angry
sad
happy
sad
cry
sleep
quiet
Das Problem, das es mir mitteilt, bash: emotion: command not found
Laut akarilimanos Kommentar hier
Dies funktioniert nicht auf meinem Ubuntu 16.04. Das ist seltsam, weil es früher „unter Ubuntu 14.04“ funktionierte.
Wie macht man das also in neueren Versionen?
Akzeptierte Antwort:
Das ist wahrscheinlich nicht der beste Weg, um das Problem anzugehen.
Von awk , alles, was Sie tun können, ist eine Befehlszeile zu erstellen, die system() geht an sh über . Sie müssen also die Argumente im sh formatieren Syntax.
Sie benötigen also:
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)
}'
Hier wird $1 von awk zitiert damit es sicher in sh eingebettet werden kann Befehlszeile, die schließlich bash ausführt mit dem Inhalt von $1 als letztes Argument, das es dann an emotion übergibt .
Das setzt Ihr sh voraus und Ihr awk Entfernen Sie nicht die speziellen Umgebungsvariablen, die bash verwendet, um Funktionen zu exportieren (wie pdksh und Derivate (wie mksh ) zum Beispiel oder dash seit 0.5.8, was Ihr Problem zwischen 14.04 und 16.04 erklärt), und dass Ihre Distribution exportierte Funktionen in bash nicht deaktiviert hat .
Wenn ja, könnten Sie es wie für ksh machen /zsh , und übergeben Sie die Definition der Funktion auf andere Weise, wie zum Beispiel:
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 beiden Fällen bedeutet das, dass ein sh und ein bash dafür ausgeführt werden. Vielleicht kannst du den $i weitergeben zu bash anders als über ein system() die jedes Mal zwei Instanzen einer Shell ausführt. Wie:
awk '{for (i=2; i<=NF; i++) printf "%s\0" $i}' |
while IFS= read -r i; do
emotion "$i"
done
Oder führen Sie die Worttrennung in bash durch direkt:
unset IFS
while read -ra fields; do
for i in "${fields[@]:1}"; do
emotion "$i"
done
done