这个问题涉及到在 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 上运行”。
那么在新版本中如何做到这一点呢?
答案1
这可能不是解决问题的最佳方法。
从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。也许您可以将 a 传递$i
给bash
其他方式,而不是通过 asystem()
每次执行 shell 的两个实例。喜欢:
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
答案2
您的脚本在 Ubuntu 16.04 上不起作用,因为/bin/sh
它链接到dash
shell,而在 Ubuntu 14.04 上则/bin/sh
链接到bash
shell。为什么这很重要? Awk 的system()
函数使用/bin/sh
并因此调用dash
Ubuntu 16.04 上的 shell。