Shell 如何预先构造awk语句以在命令行上传递给awk?

Shell 如何预先构造awk语句以在命令行上传递给awk?,shell,cygwin,awk,Shell,Cygwin,Awk,我有一个shell脚本,它将awk程序构造为字符串,然后将该字符串传递给awk。这是因为我想在awk程序中使用shell变量的值 我的代码如下所示: awk_prog="'{if (\$4~/$shell_var/) print \$1,\$2}'" echo $awk_prog awk $awk_prog $FILENAME 但是,当我将字符串传递给awk时,总是会出现以下错误: '{if ($4~/regex/) print $1,$2}' awk: '{if awk: ^ invalid

我有一个shell脚本,它将awk程序构造为字符串,然后将该字符串传递给awk。这是因为我想在awk程序中使用shell变量的值

我的代码如下所示:

awk_prog="'{if (\$4~/$shell_var/) print \$1,\$2}'"
echo $awk_prog
awk $awk_prog $FILENAME
但是,当我将字符串传递给awk时,总是会出现以下错误:

'{if ($4~/regex/) print $1,$2}'
awk: '{if
awk: ^ invalid char ''' in expression
那个错误消息是什么意思?我试过-F:开关,但没用。我怎样才能解决这个问题


谢谢。

这是由壳牌公司的报价引起的。以下工作将起作用:

awk_prog="{ if (\$4 ~ /$shell_var/) print \$1, \$2 }"
echo "$awk_prog"
awk "$awk_prog" $FILENAME
从命令行运行
awk'{print}'foo
时,shell解释并删除程序周围的引号,因此awk接收两个参数-第一个是程序文本,第二个是文件名
foo
。您的示例向awk发送程序文本
“{if…}”
,就awk而言,这是无效的语法。外部引号不应出现


在我上面给出的代码片段中,shell使用
awk_prog=
行中的引号将字符串的内容分组为单个值,然后将其分配给变量
awk_prog
。当它执行
awk“$awk_prog”…
行时,您必须引用
$awk_prog
的扩展,以便awk将程序文本作为单个参数接收。

有另一种方法将shell变量放入awk中--使用awk的
-v
选项:

awk -v pattern="$shell_var" '$4 ~ pattern {print $1, $2}' "$FILENAME"
如果有多个变量要传递给awk,请多次使用-v

如果您确实想将awk程序保存在shell变量中,请使用
printf
构建它:

awk_script="$( printf '$4 ~ /%s/ {print $1, $2}' "$shell_var" )"
awk "$awk_script" "$FILENAME"
注意printf命令中使用引号:模板周围使用单引号来保护您希望awk解释的美元符号,shell变量使用双引号。

另一个(我认为)解决方案(更简单)解决了您凭直觉试图做的事情,就是简单地使用eval。您希望shell的行为就像您按字面意思键入:

awk '{if ($4~/foo/) print $1,$2}' path awk'{if($4~/foo/)打印$1,$2}'路径 (其中foo和path是$shell_var和$FILENAME的文本内容)。要做到这一点,只需在最后一行的前面加上一个eval(可能还加上引号,但在本例中不需要),这样你的最后一行就是:

eval "awk $awk_prog $FILENAME" 评估“awk$awk_prog$FILENAME”