【问题标题】:BASH: How to use a variable as regex in AWKBASH:如何在 AWK 中使用变量作为正则表达式
【发布时间】:2015-05-17 07:27:11
【问题描述】:

我在 Awk 教程上花了几个小时,但我无法绕过那个: 我想将变量用作 awk 查询的正则表达式。这是我想要实现的示例:

#!/bin/bash
#My test array
testarray=(teststring[1078] teststringthatshouldnotmatch teststring[5845])

#myregex as a variable
regex="teststring\[.*"

#the awk
for value in ${testarray[*]}
do
echo ${value} | awk '{if ($1 ~ regex) print}'
done

我希望 Awk 匹配测试字符串 1 和 3,但它匹配所有。感谢您对此的任何了解。

【问题讨论】:

    标签: regex linux bash variables awk


    【解决方案1】:

    对于 awk 看似奇怪的行为,答案很简单。

    Shell 变量不是 awk 变量。

    虽然 shell 变量 regex 保存了您分配给它的字符串,但 awk 变量 regex 仍然是空字符串,可以匹配任何字符串。

    Shell 变量可通过 awk 中的 ENVIRON 哈希访问。

    使用这种方法不要忘记,对于从 shell 启动的任何进程,只有导出的 shell 变量会被复制到子进程的环境中。

    所以不要忘记导出您想通过 ENVIRON 访问的任何变量。

    为了让您的脚本工作,将$1 ~ regex 更改为$1 ~ ENVIRON["regex"]

    您还可以使用-v 开关在命令行上将shell 变量regex 分配给awk 变量regex。在这种情况下,您将不得不转义 shell 元字符,因此上述解决方案可能是更优雅的解决方案。

    【讨论】:

    • wrt In this case you will have to escape shell metacharacters, so probably the above mentioned solution is the more elagant one. - 不,那不是真的,只要像往常一样引用你的 shell 变量,你不需要逃避 globbing chars 等。如果你要谈论 ENVIRON你应该提到它唯一可以访问的shell变量是那些以前导出或在命令行上设置的变量。
    • 感谢提示,我添加了一个提醒,只有导出的变量才会被复制到子进程。美丽在于观察者的眼中,我试图削弱
    • ... 可能替换为可能。
    • read regex 代替固定分配将起作用,而不必记住引用了多少次,这就是我仍然更喜欢第一个版本的原因。但这当然只是个人喜好问题。
    【解决方案2】:

    我最终找到了一个方法: awk应该这样写,允许使用变量(需要用-v重新声明变量)

    awk -v test=$regex '{if (match($1, test)) {print}}'
    

    也许有更好的方法,但这个方法可以解决问题:)

    看到答案后编辑:谢谢,我会更新我的代码。

    【讨论】:

      【解决方案3】:

      在正则表达式上下文中使用字符串时,您需要对任何要转义的内容进行两次转义。总是引用你的 shell 变量,并且不需要调用 match(),你应该把条件放在 awk 脚本的条件部分,而不是在动作部分的 if 中,并且不需要显式打印。此外,.* 表示任何字符的零次或多次重复,因此匹配零个字符,因此对您的正则表达式没有任何用处。您只需要:

      regex='teststring\\['
      ...
      awk -v test="$regex" '$1~test'
      

      看:

      $ cat tst.sh
      #!/bin/bash
      #My test array
      testarray=(teststring[1078] teststringthatshouldnotmatch teststring[5845])
      
      #myregex as a variable
      regex='teststring\\['
      
      #the awk
      for value in "${testarray[@]}"
      do
          echo "$value" | awk -v test="$regex" '$1 ~ test'
      done
      $
      $ ./tst.sh
      teststring[1078]
      teststring[5845]
      

      【讨论】:

        猜你喜欢
        • 2012-07-17
        • 1970-01-01
        • 1970-01-01
        • 2011-05-29
        • 2022-06-23
        • 1970-01-01
        • 2013-05-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多