我有一个这样定义的 awk 脚本:
#!/usr/bin/env awk
BEGIN { if (!len) len = 1; end = start + len }
{ for (i = start; i < end; i++) { print $1 } }
我已将其另存为
columns
并 chmod +x
了。我想调用它,以便在遍历文件时定义 start
和 end
。我想这应该可行:
cat some_file | columns -v start=2
但事实并非如此。救命!
尝试使用:
#!/usr/bin/awk -f
作为口译员
env 是处理这个问题最简单的方法:
#!/usr/bin/env -S awk -f
添加更多选项,并确保不会干扰您的参数以及 awk 的参数:
#!/usr/bin/env -S awk -F: -f ${_} --
BEGIN {
# delete argv[1], which == ENVIRON[_]
delete ARGV[1]
} # rest of my awk program
由于 env 有 POSIX 标准,这个 shbang 应该可以帮助你解决跨 unixen 的非标准 shbang 实现的困难。
编辑
写完这篇文章后我意识到“-S”是一个不符合 POSIX 标准的 FreeBSD 环境扩展。 因此,外壳包装可能是可行的方法,但不幸的是。
不幸的是,这并不容易以可移植的方式解决。标准技术如下所示(用
/usr/bin/awk
替换您的 awk 路径):
#!/usr/bin/awk -f
BEGIN { if (!len) len = 1; end = start + len }
{ for (i = start; i < end; i++) { print $1 } }
硬编码的
awk
路径和非标准 -f
标志,使得它不能在所有 *nix 上移植。如果您只打算在一台计算机上运行脚本,那么这可能会很好地工作。但是,要制作可移植的 awk
脚本,您需要将其包装在 shell 脚本中。您可以通过以下两种方法在一个文件中完成此操作:
第一种方式是标准且易于阅读的:
#!/bin/sh
awk '
BEGIN { if (!len) len = 1; end = start + len }
{ for (i = start; i < end; i++) { print $1 } }
' "$@"
不幸的是,这在两个关键方面存在缺陷:
'
字符,您需要像这样输入:'"'"'
来“转义”它。另一个解决方案是使用
sed
去掉 sh
包装:
#!/bin/sh
exec awk "$(sed '1,2d' "$0")" "$@"
BEGIN { if (!len) len = 1; end = start + len }
{ for (i = start; i < end; i++) { print $1 } }
这有点像两行 Shabang 标题。它使用第 3 行以下的文件作为脚本参数来调用 awk。这使您可以保持漂亮的语法突出显示,并且仍然可以随心所欲地使用
'
字符。我看到的两个缺点是:
以下是这个问题的答案 -
#!/bin/awk -f
或者,可以将
awk
脚本放置在 shell 脚本中,其中仅包含 awk 命令:
#!/bin/sh
awk 'BEGIN { if (!len) len = 1; end = start + len }
{ for (i = start; i < end; i++) { print $1 } }' <file>
这避免了在 shebang 中使用
awk
并提供了将 awk 脚本作为简单 shell 脚本执行的可能性
./script
或者从当前 shell(或 shell 脚本)中使用
获取它. script
后一个选项将避免生成新的 shell 并仅执行 awk 命令。