理解shebang行

时间:2015-11-30 22:27:03

标签: linux awk

我正在阅读某人的awk脚本。从标题#!/usr/bin/env awk -f开始。 env命令没有-f选项。因此,他们必须传递awk命令的-f选项。我查看了awk的手册页。它表示 Awk扫描每个输入文件,查找与prog中指定的任何一组模式匹配的行,或者指定为-f progfile的一个或多个文件中的任何模式。对于每个模式,当文件的一行与模式匹配时,可以执行相关的操作。

根据我的理解,这意味着awk通过搜索progfile / prog中指定模式的行来处理输入文件,具体取决于你是否在awk中使用-f选项。并且基于所使用的模式,对输入文件中找到的行执行相关动作。我的问题是......运行awk脚本文件时这是如何工作的?我们没有在#!/usr/bin/env awk -f行中指定prog文件。 awk脚本会使用哪些模式?或者这是否意味着我们在运行awk脚本时必须传递progfile?如果是这种情况,是不是在脚本中指定-f选项是多余的?如果我们没有指定progfile,默认会忽略-f选项还是抛出错误?

为了更好地理解这一点,我写了一个简单的awk脚本并将其保存为test.awk

#!/usr/bin/env awk -f

BEGIN { print "START" }

当我运行时,字符串" START"被打印在屏幕上。

prachis-mbp-2:~ pskhadke$ ./test.awk
START

如果我从awk脚本的第一行删除-f选项并运行它,我会收到以下错误:

prachis-mbp-2:~ pskhadke$./test.awk
awk: syntax error at source line 1
 context is
     >>> . <<< /test.awk

类似地,

prachis-mbp-2:~ pskhadke$ awk test.awk
awk: syntax error at source line 1
 context is
     >>> test. <<< awk
awk: bailing out at source line 1

因此,由于某些原因,如果没有-f选项,它无法正确解析参数。但为什么呢?

4 个答案:

答案 0 :(得分:3)

文件的名称将附加到shebang行中命令的末尾。因此,对于具有标头test.awk的文件#!/usr/bin/env awk -f有效执行的结果命令行将是awk -f test.awk,将test.awk视为要执行的脚本文件而不是数据输入文件。

最佳插图:使用唯一内容test创建文件#!/bin/rm,使其可执行(例如chmod 755)并尝试通过运行./test来执行它。现在,该文件在哪里:)

答案 1 :(得分:3)

  

因此,他们必须为awk命令传递-f选项。

是的,这是正确的。 shebang行由内核在调用时解释。如果它读取#!/usr/bin/env awk -f,那么这意味着当该文件作为可执行文件被调用时(即,当它作为程序参数传递给七个exec函数之一时),正确的方式“执行“它是通过执行awk -f <filename>。换句话说:exec函数将使用正确的参数调用解释器,而不是尝试执行文件本身(因为它不是二进制文件)。

-f选项是必需的,因为awk(1)默认从参数中读取程序;如果您希望它从文件中读取它,则需要-f

  

根据我的理解,这意味着awk处理输入   通过搜索具有指定模式的行来搜索文件   progfile / prog取决于你是否在awk中使用-f选项。

awk(1)始终处理输入文件以查找匹配项。 -f选项仅控制从中读取awk程序的位置。如果启用,则表示第一个文件名实际上是包含awk程序的文件的名称。否则,第一个文件名是第一个开始查找模式的文件。如果未指定任何文件,则只会与stdin中的行匹配。

  

我们没有在#!/ usr / bin / env awk -f行中指定prog文件

内核为您做到了这一点。再一次,shebang行说:当你想执行这个文件(称之为X)时,请用awk -f来完成。所以它相当于awk -f X

  

如果我从awk脚本的第一行删除-f选项并运行它,我会收到以下错误:

因为那样会与:

相同
$ awk ./test.awk

这是无稽之谈,因为没有-f,它会尝试将./test.awk解释为awk程序。所以你得到一个错误。

答案 2 :(得分:2)

#!/usr/bin/env awk -f

在附加脚本名称后,将#!后的字符串作为命令调用。

如果您阅读env命令的文档,您将看到(在没有任何NAME=VALUE或其他选项的情况下)它将其第一个参数作为命令调用,传递任何以下参数到该命令。因此env会调用awk -f name-of-script

您需要-f的原因仅仅是因为awk处理其命令行参数的方式。如果在awk命令行上传递字符串而未指定选项名称,则会将该字符串计算为awk代码:

$ awk 'BEGIN {print "hello, world"}'
hello, world

要告诉awk执行文件内容,您必须使用-f选项:

$ echo 'BEGIN { print "hello, world"}' > hello.awk
$ awk -f hello.awk
hello, world

与大多数其他口译员相比,这实际上有点不寻常。例如,perl命令默认将命令行参数视为脚本名称;要在命令行上传递Perl代码,您必须使用-e选项:

$ perl -e 'print "hello, world\n"'
hello, world

大多数炮弹都是一样的。

请注意,某些较旧的系统会限制您在#!行上可以拥有的参数数量,因此#!/usr/bin/env awk -f可能无效。

如果您知道awk解释器命令的确切位置,则可以直接使用它而不是使用/usr/bin/env

#!/usr/bin/awk -f

有关#!/usr/bin/env黑客的讨论,请参阅this questionmy answer

答案 3 :(得分:1)

Shebang行将由内核解释,它将调用shebang之后指定的解释器,并将可执行文件名(您的脚本)作为参数。请参阅man 2 execve,“解释程序脚本”部分

相关问题