运行另一个命令的输出,并进行变量替换

运行另一个命令的输出,并进行变量替换

在 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 变量。

处理参数会比较棘手:您可以:

  1. 将变量作为空格分隔的字符串传递,并让文件参数的数量可变:

    awkline "var1 var2 var3" "awk body" file ...
    
  2. 或者让函数总是从 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[@]}" "$@"
}     

相关内容