【问题标题】:awk set command line options in scriptawk 在脚本中设置命令行选项
【发布时间】:2020-03-26 03:18:07
【问题描述】:

我很好奇如何在 awk 脚本中设置命令行选项,例如 -F 用于字段分隔符。我尝试像这样写shebang线

#!/usr/bin/awk -F ":" -f

并得到以下错误:

awk: 1: unexpected character '.'

对于这个例子,我可以用

BEGIN {FS=":"}

但我仍然想知道设置所有这些选项的方法。提前致谢。

编辑:

让我们使用另一个应该易于测试的示例。 输入文件:

1
2
3
4

test.awk:

#!/usr/bin/awk -d -f
{num += $1}
END { print num}

运行

/usr/bin/awk -d -f test.awk inputfile

将获得10 并生成一个名为awkvars.out 的文件,其中包含一些awk 全局变量。 但是

./test.awk inputfile

会得到

awk: cmd. line:1: ./test.awk
awk: cmd. line:1: ^ syntax error
awk: cmd. line:1: ./test.awk
awk: cmd. line:1:   ^ unterminated regexp

如果我从 shebang 行中删除 '-d',

./test.awk inputfile

通常会输出 10。

我的问题是有没有办法在test.awk文件中写“-d”来生成awkvars.out文件?

【问题讨论】:

标签: awk


【解决方案1】:

回答OP问题,超出FS的设置。

简短的回答:你不能使用带有'#!'的多个选项,因为你需要告诉 awk 从标准输入 (-f-) 读取程序,所以你很不走运。

长答案:

当使用shebang (#!) 时,单个参数有限制(作为第一个参数传递给命名程序。所以一般来说:

#! /path/to/prog arg1
input-1
input-2

将执行/path/to/prog arg1,文件内容(包括前导shebang)可作为标准输入。 这是过于简单化了,实际规则更复杂。,见https://unix.stackexchange.com/questions/87560/does-the-shebang-determine-the-shell-which-runs-the-script

鉴于这个参数的限制,在执行 awk 时,唯一有效且必需的参数是“-f”,这表明 awk 程序是在 STDIN 上提供的。您可以在前面添加一些不带任何参数的其他选项,例如“传统”(例如,“-Pf-”将强制执行 POSIX 行为)。

据我所知,所有“有趣”的选项(设置 FS、RS、ORS 等)都需要用空格与“-f-”隔开,因此无法将它们嵌入命令行,然后在脚本中使用 'BEGIN { ... }' 或类似的。

最后,尝试#! /usr/bin/awk -f- -F, 将尝试查找与awk -f' -F' 相同的程序,并将查找名为“- -F”的文件。通常不是很有用,而且不会设置FS。

【讨论】:

    【解决方案2】:

    假设以下是我们的 Input_file,我们将在此处用于所有提到的解决方案。

    cat Input_file
    a,b,c,d
    ab,c
    


    设置字段分隔符的第一种方法: 第一种简单的方法是在awk 程序文件的BEGIN 部分中设置FS 值。以下是我们的.awk 文件。

    cat file1.awk
    BEGIN{
      FS=","
    }
    {
      print $1"..."$2
    }
    

    现在当我们运行代码时会出现以下输出:

    /usr/local/bin/awk -f file1.awk Input_file
    a...b
    ab...c
    


    设置字段分隔符的第二种方式:第二种方式将在读取 Input_file 之前传递FS 值,如下所示。

    /usr/local/bin/awk -f file.awk FS="," Input_file
    

    示例:下面是file.awk 文件,其中包含awk 代码。

    cat file.awk
    {
     print $1".."$2
    }
    

    现在当我们使用awk -f .. 命令运行awk 文件时,结果如下。

    /usr/local/bin/awk -f file.awk FS=","  Input_file
    a..b
    ab..c
    

    这意味着它在上述程序中将字段分隔符设为,



    设置字段分隔符的第三种方法: 我们可以在awk -f 程序中设置字段分隔符,就像我们对通常的awk 程序使用-F',' 选项一样跟随。

    /usr/local/bin/awk -F',' -f  file.awk Input_file
    a..b
    ab..c
    


    设置字段分隔符的第四种方法: 我们可以在运行file.awk 脚本时在命令行中使用-v 选项将字段分隔符作为变量提及,如下所示。

    /usr/local/bin/awk -v FS=',' -f  file.awk Input_file
    

    【讨论】:

    • 感谢您的回答。现在我可以在脚本文件中分配给 FS 或作为命令行参数传递。我也可以使用 -F 命令行选项。我的问题是,我可以在脚本中而不是在命令行中使用 -F 选项吗?如果可以,我该怎么做?
    • @Zhu,是的,您可以在BEGIN 部分进行设置,我提供了 4 个选项来设置它,请检查它们并让我知道您是否有任何疑问?
    • 这些方式都可以,但除了第三种方式使用-F选项外,其他方式都使用变量FS。事实上,我的问题是我是否可以在脚本中使用命令行选项,例如 -M 用于 bignum,-W 用于 gawk-opt 等等。我认为 -F 只是恰好能够被 FS 变量替换的选项之一?
    • @Zhu,我没有使用这些选项,但如果-F 被允许,那么这些也应该尝试我的第四个选项,使用-v 这些选项并尝试一次?我无法测试它,因为我需要一个用例。让我知道情况如何?
    • 我已经编辑了问题并添加了一个示例。我认为您提到的方式需要与选项对应的 awk 变量?
    【解决方案3】:

    永远不要使用 shebang 来调用 awk,因为它会剥夺你在调用 awk 之前将 shell 参数分离为 awk 参数和 awk 变量以及在 shell 中执行任何其他更好的操作(例如使用 getopts 解析 arg)的能力。只需从您的 shell 脚本中调用 awk。

    另外,不要将您的 shell 脚本命名为 test.awk,因为它是一个 shell 脚本。它在 awk 中实现的事实是无关紧要的。没有理由创建一个文件,您有时将其称为 awk file 以进行 awk 解释,而有时将其称为 file 以进行 shell 解释。

    【讨论】:

      猜你喜欢
      • 2018-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多