【问题标题】:Awk script: How to prevent ARGV from being treated as an input file nameawk 脚本:如何防止 ARGV 被视为输入文件名
【发布时间】:2013-09-16 09:49:07
【问题描述】:

awk 脚本似乎将ARGV[1]ARGV[ARGC] 视为输入文件。

有没有办法让 awk 将 ARGV 视为简单参数而不是输入文件

例子:

test.awk

#!/usr/bin/awk -f
BEGIN {title=ARGV[2]}
{if ($1=="AA") {print title}}

数据文件

AB
BA
AA
CC

$ test.awk dat 'My Interesting Title'

我的有趣标题 awk:test.awk:3:致命:无法打开文件“我的有趣标题”进行阅读(没有这样的文件或目录)

【问题讨论】:

    标签: awk


    【解决方案1】:

    您可以随时修改ARGV。 awk 依次处理ARGV 的元素,所以如果在处理过程中修改它们,可以安排读取不同的文件或者不将某些参数作为文件名处理。特别是,如果您在BEGIN 块中修改ARGV,则一切皆有可能。例如,以下 sn-p 导致 awk 即使在传递参数时也从标准输入读取,并将参数保存在名为 args 的数组中:

    awk '
        BEGIN {for (i in ARGV) {args[i] = ARGV[i]; delete ARGV[i]}}
        …
    ' hello world
    

    如果你只想跳过第一个参数,只删除它:

    awk '
        BEGIN {title = ARGV[1]; delete ARGV[1]}
        $1 == "AA" {print title}
    ' 'My Interesting Title' input.txt
    

    但是,这是不寻常的,因此可能被认为难以维护。考虑使用 shell 包装器并通过环境变量传递标题。

    #!/bin/sh
    title=$1; shift
    awk '
        $1 == "AA" {print ENV["title"]}
    ' "$@"
    

    您还可以将字符串作为 awk 变量传递。请注意该值会经历反斜杠扩展。

    awk -v 'title=My Interesting Title\nThis is a subtitle' '
        $1 == "AA" {print title}  # prints two lines!
    ' input.txt
    

    【讨论】:

      【解决方案2】:

      这样的?

      $ awk -v title='My Interesting Title' '$0 ~ /AA/ {print title}1' input
      AB
      BA
      My Interesting Title
      AA
      CC
      

      【讨论】:

      • 需要注意的是,title 的值会经历反斜杠扩展。
      【解决方案3】:

      是的:

      BEGIN{title=ARGV[2];ARGV[--ARGC]=""}
      $1=="AA" {print title}
      

      但你可能想要这个:

      $ cat tst.sh
      awk -v title="$2" '$1=="AA" {print title}'
      

      有关将 shell 变量的值传递给 awk 脚本的这些方法和其他方法的详细信息,请参阅 http://cfajohnson.com/shell/cus-faq-2.html#Q24

      顺便说一句,注意不管你用的是这个脚本还是你原来的,你文件的内容都是调用awk的shell脚本,而不是awk脚本,所以后缀不应该是.awk,应该是@ 987654325@ 或类似号码。

      【讨论】:

        【解决方案4】:

        您可以在读取参数后减少 ARGC,以便awk 仅将第一个参数视为输入文件:

        #!/bin/awk -f
        
        BEGIN {
            for (i=ARGC; i>2; i--) {
                print ARGV[ARGC-1];
                ARGC--;
            }
        }
        …
        

        或者,您可以在读取所有参数后重置 ARGC:

        #!/bin/awk -f
        
        BEGIN {
            for (i=0; i<ARGC; i++) {
                print ARGV[ARGC-1];
            }
            ARGC=2;
        }
        …
        

        这两种方法都将正确处理myawkscript.awk foobar foo bar …,就好像 foobar 是唯一要处理的文件一样(当然,如果您希望将前两个参数作为文件等,您可以将 ARGC 设置为 3)。

        【讨论】:

          【解决方案5】:

          也允许

          awk 'BEGIN {title=ARGV[2]}
                     {if ($1=="AA") {print title}}
              ' input.txt -v "title=My Interesting Title"
          

          ARGV 的参数也是varname=VarContent 格式的任何字符串(命令行参数)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-01-05
            • 2013-02-28
            • 1970-01-01
            • 1970-01-01
            • 2019-12-18
            • 1970-01-01
            • 1970-01-01
            • 2020-05-11
            相关资源
            最近更新 更多