2010-07-02 60 views
3

我有一个shell脚本构造一个awk程序作为一个字符串,然后将该字符串传递给awk。这是因为我想在awk程序中使用shell变量的值。如何预先构建awk语句以在命令行上传递给awk?

我的代码如下所示:

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:开关,但它没有帮助。我怎样才能解决这个问题?

谢谢。

回答

5

这是由shell引用引起的。下面的工作:

awk_prog="{ if (\$4 ~ /$shell_var/) print \$1, \$2 }" 
echo "$awk_prog" 
awk "$awk_prog" $FILENAME 

当你在命令行中运行awk '{ print }' foo,外壳解释等AWK接收两个参数删除程序周围的报价 - 首先是程序文本和第二个是文件名foo。你的例子是发送awk程序文本'{if ...}',就awk而言,这是无效的语法。外部引号不应该存在。

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

4

还有另一种方式来获得你的shell变量到awk的 - 使用awk的-v选项:如果

awk -v pattern="$shell_var" '$4 ~ pattern {print $1, $2}' "$FILENAME" 

使用-v多次,你有几个变量传递给AWK。

如果你真的想在一个shell变量来保存你的awk程序,构建它使用printf

awk_script="$(printf '$4 ~ /%s/ {print $1, $2}' "$shell_var")" 
awk "$awk_script" "$FILENAME" 

注意使用printf命令引号:单引号括起来的模板,以保护美元您希望awk解释的标志,用于shell变量的双引号。

1

另一个(我认为)解决你直觉上试图做的(IMO简单)解决方案只是使用eval。您希望壳的行为就好像你从字面上键入:

 
awk '{if ($4~/foo/) print $1,$2}' path 

(其中foo和路径是$ shell_var和$文件名的文字内容)。要做到这一点,只需在最后一行的前面打一个eval(也许引号是好的措施,但在这种情况下它们不是必需的),以便您的最后一行是:

 
eval "awk $awk_prog $FILENAME"