如何在代码中扩展awk变量?

3

假设我向awk脚本传递了一些变量:

$AWK -f script.awk -v var01="foo" var02="bar"

在脚本中,我获取了一些模式:

# pattern01 var01
/pattern01/ {
        if (??? == "foo") print
}

我想将变量"$2"("var01")扩展为其给定值。 我一直在尝试使用gawk,似乎可以以下列方式扩展变量:

print $$x

但是,由于某些原因,在第一个示例中无法正常工作,我需要保持POSIX兼容性。是否有可能在给定的示例中扩展变量?

(注意:如果可能,我希望保留此行为,因此我不想使用其他工具或shell扩展的解决方法)

在shell中的等效写法:

file01:
        foobar
        some random text
        pattern01 var01
        more random text...

code.sh:
        #!/bin/sh
        var01="Hello"
        x="$(grep '^pattern01' file01 | awk '{print $2}')"
        eval echo "$"$x # prints Hello

因为我正在打印找到的模式,而在给定的示例中,它将是"pattern01 var01":$1="pattern01",$2="var01"。 - MayAccer
@MayAccer,var02是一个shell变量吗?您能否提供更多关于它的信息呢? - RavinderSingh13
"var02"是由标志“-v”定义的变量,然后调用awk脚本来处理某个文件,该文件可能有一些模式后跟字符串“var01/var02”,我想将该字符串转换为同名变量。(我将编辑并添加相应的shell脚本等效内容) - MayAccer
只需按其名称使用变量,就像在C语言中一样。例如:print var01 - Ed Morton
只有当变量的内容出现在某个模式中时,才应该打印它,因此我只有在获取某个模式后才能知道它的名称。 - MayAccer
awk 中使用变量,请参考此帖子:https://dev59.com/cGIk5IYBdhLWcg3wqPsi#19075707 - Jotne
3个回答

1
我找到了一种解决方案,通过将变量设置为环境的一部分,然后使用名称调用特殊变量“ENVIRON”(因为它充当字典)。
# pattern01 var01
/pattern01/ {
        if (ENVIRON[$2] == "foo") print
}

我认为在 BEGIN 阶段手动创建字典,可以实现相同的行为,而不需要使用环境。

1
使用POSIX awk时,无法通过变量名称查找变量的值。相反,考虑使用数组来存储值。这并不是最优雅的方法,但是可以实现可移植性: $AWK -e 'BEGIN { v["var01"] = "foo" ; v["var02"] = "bar" }' -f script.awk

script.awk

# pattern01 var01
/pattern01/ {
        if ( v[$2] == "foo") print
}

如果您知道将会使用新的GNU AWK版本,并且可以使用扩展功能,那么您可以使用SYMTAB数组。来自手册页面:

SYMTAB An array whose indices are the names of all currently defined global variables and arrays in the program. The array may be used for indirect access to read or write the value of a variable:

  foo = 5
  SYMTAB["foo"] = 4
  print foo    # prints 4
$AWK -f script.awk -v var01="foo" var02="bar"

script.awk
# pattern01 var01
/pattern01/ {
        if ( SYMTAB[$2] == "foo") print
}

两种方法都可以避免创建环境变量,这可能会影响其他程序,并且可能难以扩展。


正如我所预料的,字典是唯一可移植的解决方案(至少根据我的测试)。在我的情况下,环境已经清理干净,但这个解决方案更少出错,因此我将其标记为更好的解决方案。 - MayAccer

0

你能试试这个吗?

var01="Hello"
x="$(grep '^pattern01' file01 | awk '{print $2}')"
echo ${!x}

希望这能有所帮助。 谢谢,


可以在shell脚本(特别是bash)中工作,并且比使用“eval”更好。但问题不在于在shell脚本中实现此行为。 - MayAccer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接