代码之家  ›  专栏  ›  技术社区  ›  Dr. Hans-Peter Störr

如何在awk中使用一个shebang的多个参数(即#!)?

  •  109
  • Dr. Hans-Peter Störr  · 技术社区  · 14 年前

    我想执行一个 gawk 脚本 --re-interval 使用shebang。“天真”的方法

    #!/usr/bin/gawk --re-interval -f
    ... awk script goes here
    

    不起作用,因为gawk是用第一个参数调用的 "--re-interval -f" (不在空白处分割),这是它不理解的。有办法解决这个问题吗?

    当然,您不能直接调用gawk,而是将其包装成一个shell脚本,该脚本拆分第一个参数,或者生成一个shell脚本,然后调用gawk并将该脚本放入另一个文件中,但我想知道是否有某种方法可以在一个文件中执行此操作。

    shebang线的行为因系统而异-至少在 Cygwin 它不会用空格分隔参数。我只关心如何在一个这样的系统上运行;脚本并不意味着是可移植的。

    10 回复  |  直到 7 年前
        1
  •  24
  •   Aaron McDaid    10 年前

    这对我来说似乎很管用。

    #!/bin/sh
    arbitrary_long_name==0 "exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"
    
    
    # The real awk program starts here
    { print $0 }
    

    注意 #! /bin/sh ,因此该脚本首先被解释为shell脚本。

    起初,我只是试着 "exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@" ,但awk将其视为一个命令,无条件地打印出每一行输入。所以我把 arbitrary_long_name==0 -它应该一直失败。你可以用一些乱七八糟的绳子代替它。基本上,我是在awk中寻找一个不会对shell脚本产生负面影响的错误条件。

    在shell脚本中 任意_long_name==0 定义一个称为 arbitrary_long_name 并将其设置为 =0 .

        2
  •  156
  •   mklement0    10 年前

    shebang线从未被指定为POSIX、SUS、LSB或任何其他规范的一部分。阿飞,它甚至没有适当的文件。

    对于它的作用有一个大致的共识:在 ! 以及 \n exec 它。假设是 ! 以及 \n个 是到解释器的完全绝对路径。如果它包含空白,会发生什么,目前还没有共识。

    1. 有些操作系统只是把整个过程当作路径。毕竟,在大多数操作系统中,空格或破折号在路径中是合法的。
    2. 一些操作系统以空白分割,将第一部分作为解释器的路径,其余部分作为单独的参数。
    3. 一些操作系统在 第一 空白并将前面的部分视为指向interpeter的路径,其余部分视为 单一的 争论(这就是你所看到的)。
    4. 有些甚至不支持shebang线 完全 .

    谢天谢地,1。和4。好像已经死了,但是3。是相当广泛的,所以你不能仅仅依靠能够通过一个以上的论点。

    而且由于命令的位置在POSIX或SUS中也没有指定,因此通常通过传递可执行文件的 名称 env 以便 可以确定可执行文件的位置;例如:

    #!/usr/bin/env gawk
    

    [很明显,这个 仍然 假设一个特定的路径 环境 ,但它所处的系统很少 /bin ,所以这通常是安全的。地点 环境 gawk 或者更糟的是 python ruby spidermonkey .]

    也就是说你不能用 任何 论据 完全 .

        3
  •  12
  •   raphink    13 年前

    我遇到了同样的问题,由于shebang(至少在Linux上)处理空白的方式,没有明显的解决方案。

    但是,你可以在shebang中传递几个选项,只要它们是 空头期权 他们可以是 串联的 (GNU方式)。

    例如,你不能

    #!/usr/bin/foo -i -f
    

    但是你可以

    #!/usr/bin/foo -if
    

    显然,只有当选项具有短等价物且不带参数时,这才有效。

        4
  •  12
  •   Moritz    8 年前

    在Cygwin和Linux下,shebang路径解析为一个参数后的所有内容都被解析到程序中。

    可以用另一个 awk 舍邦内的剧本:

    #!/usr/bin/gawk {system("/usr/bin/gawk --re-interval -f " FILENAME); exit}
    

    这将执行 {system("/usr/bin/gawk --re-interval -f " FILENAME); exit} 在awk中。
    这将执行 /usr/bin/gawk --re-interval -f path/to/your/script.awk 在你的系统外壳里。

        5
  •  12
  •   unode    6 年前

    虽然不是完全可移植的,但从coreutils 8.30和 according to its documentation 您将能够使用:

    #!/usr/bin/env -S command arg1 arg2 ...
    

    因此:

    $ cat test.sh
    #!/usr/bin/env -S showargs here 'is another' long arg -e "this and that " too
    

    你将得到:

    % ./test.sh 
    $0 is '/usr/local/bin/showargs'
    $1 is 'here'
    $2 is 'is another'
    $3 is 'long'
    $4 is 'arg'
    $5 is '-e'
    $6 is 'this and that '
    $7 is 'too'
    $8 is './test.sh'
    

    如果你好奇的话 showargs 是:

    #!/usr/bin/env sh
    echo "\$0 is '$0'"
    
    i=1
    for arg in "$@"; do
        echo "\$$i is '$arg'"
        i=$((i+1))
    done
    

    原始答案 here .

        6
  •  5
  •   bfontaine cat-walk    6 年前
    #!/bin/sh
    ''':'
    exec YourProg -some_options "$0" "$@"
    '''
    

    上面的shebang技巧比 /usr/bin/env .

        7
  •  3
  •   bta    14 年前

    在gawk手册(http://www.gnu.org/manual/gawk/gawk.html)中,第1.14节的末尾注意,从shebang行运行gawk时,只应使用一个参数。它说,操作系统将把所有经过“目瞪口呆”之路的东西当作一个单独的论点。也许有另一种方法可以指定 --re-interval 选择?也许你的脚本可以引用shebang行中的shell,run gawk 作为命令,并将脚本文本包含为“here文档”。

        8
  •  3
  •   conny scipilot    7 年前

    为什么不使用 bash gawk 本身,跳过shebang,阅读脚本,并将其作为文件传递给 gawk [--with-whatever-number-of-params-you-need] ?

    #!/bin/bash
    gawk --re-interval -f <(gawk 'NR>3' $0 )
    exit
    {
      print "Program body goes here"
      print $1
    }
    

    (-当然也可以通过例如。 sed tail ,但我认为有些美只取决于 猛击 呆呆的 本身;)

        9
  •  0
  •   Dr. Hans-Peter Störr    11 年前

    只是为了好玩:下面有一个非常奇怪的解决方案,它通过文件描述符3和4重新路由stdin和程序。您还可以为脚本创建一个临时文件。

    #!/bin/bash
    exec 3>&0
    exec <<-EOF 4>&0
    BEGIN {print "HALLO"}
    {print \$1}
    EOF
    gawk --re-interval -f <(cat 0>&4) 0>&3
    

    有一件事很烦人:shell在脚本上进行变量扩展,因此必须引用每个$(如脚本第二行中所做的)并且可能不止这些。

        10
  •  -1
  •   lharper71    11 年前

    对于便携式解决方案,请使用 awk 而不是 gawk ,调用标准BOURNE shell( /bin/sh )带着你的谢邦,召唤 锥子 直接将程序作为here文档而不是通过stdin在命令行上传递:

    #!/bin/sh
    gawk --re-interval <<<EOF
    PROGRAM HERE
    EOF
    

    注: -f 论证 锥子 . 就这样离开了 stdin 可用于 锥子 从中读取输入。假设你有 呆呆的 安装在您的 PATH ,这就实现了我认为您试图使用原始示例所做的一切(假设您希望文件内容是awk脚本,而不是输入,我认为shebang方法会将其视为输入)。