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