在 bash 中,我经常使用以下命令运行 awk 程序许多预设变量。大多数时候我在 bash 和 awk 中使用相同的变量名,因此我像下面这样调用 awk:
awk -v var1="$var1" -v var2="$var2" -v var3="$var3" ....... '
# awk code
'
当我需要输入许多变量名时,这会变得有点乏味。理想情况下,我希望能够运行如下命令:
$(awkline var1 var2 var3 ......) '
# awk code
'
其中命令“awkline”的输出是 awk 命令的正确格式。例如,“awkline”程序可能如下所示:
#!/bin/bash
line="awk"
for i in $*; do line="$line -v $i="'"$'"$i"'"'; done
echo $line
如果我运行“awkline ab c”,我会得到我期望的结果:
awk -v a="$a" -v b="$b" -v c="$c"
但是,如果我尝试运行类似 $(awkline abc) 的命令,awk 中的变量 a 的值将变为(包括引号)“$a”,而不是我想要的 a 的值。如何用变量 a 的值替换所有出现的 $a,以便可以运行 awkline 命令?
答案1
不要制作awkline
单独的脚本:这意味着您必须导出要传递给 awk 的所有变量。您可以将其作为添加到 .bashrc 的函数。这样,它会在当前 shell 进程中运行并可以访问您的 shell 变量。
处理参数会比较棘手:您可以:
将变量作为空格分隔的字符串传递,并让文件参数的数量可变:
awkline "var1 var2 var3" "awk body" file ...
或者让函数总是从 stdin 读取并允许可变数量的变量名:
cat file1 file2 ... | awkline var1 var2 ... "awk body"
编写第一个代码:
awkline () {
local variables=$1
local body=$2
shift 2
local files=("$@")
set -- $variables # no quotes here, now the positional params are the var names
local awk_cmd=(awk)
for var; do
awk_cmd+=(-v "$var=${!var}")
done
"${awk_cmd[@]}" "$body" "${files[@]}"
}
考虑到您评论中的用法,可以简化:
awkline () {
local awk_vars=()
for var in $1; do # no quotes here
awk_vars+=(-v "$var=${!var}")
done
shift
awk "${awk_vars[@]}" "$@"
}