BEGIN:通过采购运行时,在简单的 awk 脚本中找不到命令

BEGIN:通过采购运行时,在简单的 awk 脚本中找不到命令

awk今天正在学习,但我无法成功地让最简单的脚本工作。

#!/usr/bin/env -S awk -f
BEGIN { }
{ }
END { }

这输出BEGIN: command not found

甚至

#!/usr/bin/env -S awk -f
{}

这输出{}: command not found

当我启动时$ /usr/bin/env -S awk -f,我确实有 awk 可执行文件显示其默认输出。

$ awk --version说它是 awk 版本 5.0.1 ,在 nixos 19.09 上。

我需要使用/usr/bin/env,因为 nixos 文件不遵循传统的 FHS 目录层次结构。

我怀疑我错过了一些明显的东西,但查看 awk 教程和 SO 问题目前还没有给我任何线索。

编辑:我用来启动脚本的命令行

ls -l | . testawk.sh

答案1

采购是不一样执行。具体来说,采购需要一个可以在当前 shell 中执行的命令列表。以下内容来自 bash help .

.: .文件名[参数]

在当前 shell 中执行文件中的命令。

在当前 shell 中读取并执行来自 FILENAME 的命令。 $PATH 中的条目用于查找包含 FILENAME 的目录。如果提供了任何 ARGUMENTS,它们将在执行 FILENAME 时成为位置参数。

因此,当您运行时. file,您的 shell 将读取该文件并执行它找到的每个命令。然而,这意味着 shebang 行将被忽略并被视为常规注释。因此,您的 shell 而不是 awk 正在尝试执行BEGIN.

为了避免这种情况,您应该执行脚本而不是获取它。如果,出于某种原因,你只是必须获取它,在脚本中编写 awk 命令:

awk '
BEGIN { }
{ }
END { }'

然后,你可以做

ls | . ./a.awk 

虽然我实在想不出你为什么想要这样做。


顺便说一句,您应该知道.(或bash 中的 )默认情况下source会在您的文件中查找文件名。$PATH因此,如果您运行. foo,并且foo当前目录中有一个文件,并且foo中的任何目录中有一个文件$PATH,那么将获取的文件是您中的文件$PATH,而不是当前目录中的文件。为了避免这种情况,请在采购时始终使用完整路径:. ./foo

答案2

切勿使用 shebang 调用 awk,因为这会剥夺您将脚本参数分为应在 shell 中完成的部分与应在 awk 中完成的部分的能力,以及将 awk 参数与 awk 变量赋值分开的能力。只需将您的脚本写为:

#!/usr/bin/env bash

/usr/bin/env awk '
BEGIN { }
{ }
END { }
' "$@"

有时您想要修改它来执行诸如设置 awk 变量之类的操作:

#!/usr/bin/env bash

rs="$1"
fs="$2"
shift 2

/usr/bin/env awk -v RS="$rs" -F "$fs" '
BEGIN { }
{ }
END { }
' "$@"

这应该像上面一样微不足道,但如果您使用 shebang 调用 awk,则无法执行此操作。

答案3

正如 AdminBee 的评论中提到的,脚本的调用方式是错误的(获取内容)。

正确的做法是:

ls -l | ./test.awk

或者,更简单地,不依赖于该#!行:

ls -l | awk -f ./test.awk

相关内容