Awk脚本:如何防止ARGV被视为输入文件名

时间:2013-09-16 09:49:07

标签: awk

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

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

示例:

test.awk

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

dat文件

AB
BA
AA
CC

$ test.awk dat 'My Interesting Title'
  
    
      

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

    
  

5 个答案:

答案 0 :(得分:7)

您可以随时修改ARGV。 Awk依次处理ARGV的元素,因此如果您在处理过程中修改它们,您可以安排读取不同的文件或不将某些参数视为文件名。特别是,如果您修改ARGV块中的BEGIN,则一切皆有可能。例如,以下代码段会导致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

答案 1 :(得分:5)

这样的东西?

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

答案 2 :(得分:1)

是:

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而不是awk脚本的shell脚本,因此后缀不应该是.awk,它应该是是.sh或类似。

答案 3 :(得分:0)

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

#!/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)。

答案 4 :(得分:0)

也允许

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

参数也是格式varname=VarContent

的任何字符串(命令行参数)