Bash

如何在 awk 內的 bash 腳本中呼叫 bash 函式?

  • October 26, 2017

此問題與在 AWK 中使用 bash shell 函式有關

我有這個程式碼

#!/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

我有這個文件:

cat    smile    happy   laugh
dog    angry    sad
mouse  happy    
wolf   sad      cry
fox    sleep    quiet 

輸出應該是這樣的:

smile
happy
laugh
angry
sad
happy    
sad
cry
sleep
quiet 

它告訴我的問題bash: emotion: command not found

根據 akarilimano在這裡的評論

這不適用於我的 Ubuntu 16.04。這很奇怪,因為它曾經“在 Ubuntu 14.04.

那麼如何在較新的版本中做到這一點?

這可能不是解決問題的最佳方法。

從 開始awk,您所能做的就是建構一個system()傳遞給sh. 因此,您需要在sh語法中格式化參數。

所以你需要:

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 \"$@\"'\'' bash " sh_quote($1)
 }'

這裡引用 awk$1以便它可以安全地嵌入到最終以最後一個參數的內容sh執行的命令行中,然後將其傳遞給.bash``$1``emotion

假設您sh和您awk沒有剝離bash用於導出函式的特殊環境變數(例如,類似pdksh和衍生品(例如mksh),或者dash自 0.5.8 以來解釋了您的 14.04 與 16.04 問題),並且您的發行版沒有中禁用導出功能bash

如果是這樣,您可以像 for ksh/那樣做zsh,並以其他方式傳遞函式的定義,例如:

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 \"$@\"'\'' bash " \
                     sh_quote($1)
 }'

在這兩種情況下,這意味著為它執行一個 sh 和一個 bash。也許您可以將 傳遞$ibash其他方式,而不是通過system()每次執行兩個 shell 實例的 a 。像:

awk '{for (i=2; i<=NF; i++) printf "%s\0" $i}' |
 while IFS= read -r i; do
   emotion "$i"
 done

或者bash直接做分詞:

unset IFS
while read -ra fields; do
 for i in "${fields[@]:1}"; do
   emotion "$i"
 done
done

引用自:https://unix.stackexchange.com/questions/400530