Masalah ini terkait dengan Menggunakan fungsi bash shell di dalam AWK
Saya punya kode ini
#!/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
dan saya memiliki file ini:
cat smile happy laugh
dog angry sad
mouse happy
wolf sad cry
fox sleep quiet
Outputnya akan seperti ini:
smile
happy
laugh
angry
sad
happy
sad
cry
sleep
quiet
Masalah ini memberi tahu saya bash: emotion: command not found
Menurut komentar akarilimano di sini
ini tidak berfungsi di Ubuntu 16.04 saya. Ini aneh, karena dulu berfungsi “di Ubuntu 14.04.
Jadi bagaimana melakukannya di versi yang lebih baru?
Jawaban yang Diterima:
Itu mungkin bukan cara terbaik untuk mengatasi masalah.
Dari awk
, yang dapat Anda lakukan hanyalah membuat baris perintah yang system()
lolos ke sh
. Jadi, Anda memerlukan argumen untuk diformat dalam sh
sintaks.
Jadi, Anda memerlukan:
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)
}'
Di sini mengutip $1
awk's sehingga dapat disematkan dengan aman di sh
baris perintah yang akhirnya menjalankan bash
dengan isi $1
sebagai argumen terakhir, yang kemudian diteruskan ke emotion
.
Itu mengasumsikan sh
. Anda dan awk
. Anda jangan hapus variabel lingkungan khusus yang bash
gunakan untuk mengekspor fungsi (seperti pdksh
dan turunannya (seperti mksh
) lakukan misalnya, atau dash
sejak 0.5.8 yang menjelaskan masalah 14.04 vs 16.04 Anda), dan bahwa distribusi Anda belum menonaktifkan fungsi yang diekspor di bash
.
Jika ya, Anda bisa melakukannya seperti untuk ksh
/zsh
, dan berikan definisi fungsi dengan cara lain, seperti:
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)
}'
Dalam kedua kasus, itu berarti menjalankan satu sh dan satu bash untuk itu. Mungkin Anda bisa melewati $i
ke bash
cara lain selain melalui system()
yang mengeksekusi dua instance shell setiap kali. Seperti:
awk '{for (i=2; i<=NF; i++) printf "%s\0" $i}' |
while IFS= read -r i; do
emotion "$i"
done
Atau lakukan pemisahan kata di bash
langsung:
unset IFS
while read -ra fields; do
for i in "${fields[@]:1}"; do
emotion "$i"
done
done