Bash
如何在 awk 內的 bash 腳本中呼叫 bash 函式?
我有這個程式碼
#!/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。也許您可以將 傳遞
$i
給bash
其他方式,而不是通過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