我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