调用一个脚本,该脚本有一个 awk shebang,带有参数(vars)

问题描述 投票:0回答:5

我有一个这样定义的 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

但事实并非如此。救命!

shell awk shebang
5个回答
69
投票

尝试使用:

#!/usr/bin/awk -f

作为口译员


16
投票

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 环境扩展。 因此,外壳包装可能是可行的方法,但不幸的是。


5
投票

不幸的是,这并不容易以可移植的方式解决。标准技术如下所示(用

/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 } }
' "$@"

不幸的是,这在两个关键方面存在缺陷:

  1. 如果您的 awk 脚本包含
    '
    字符,您需要像这样输入:
    '"'"'
    来“转义”它。
  2. 如果您使用具有语法突出显示功能的文本编辑器,您将无法正确突出显示 awk 脚本。

另一个解决方案是使用

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。这使您可以保持漂亮的语法突出显示,并且仍然可以随心所欲地使用

'
字符。我看到的两个缺点是:

  1. 这可能读起来不直观。
  2. 如果您使用代码检查器,它可能不是这样的。

1
投票

以下是这个问题的答案 -

#!/bin/awk -f 

0
投票

或者,可以将

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 命令。

© www.soinside.com 2019 - 2024. All rights reserved.