使用 shebang 使 STDIN 可执行

使用 shebang 使 STDIN 可执行

我有一个列出数据库文件的程序。

它直接从 shell 中调用,就像

db filename

列出整个文件,或者类似

db 'filename :: conditions'

仅列出选定的元素...


另一种方法是使用包含所有参数的文件来调用它。

db < parameterfile

内容如下(与上面''中的内容完全相同):

filename
::
conditions

现在我想让这样的文件可执行。这样我就可以打电话了./parameterfile

我认为使用 shebang#!/usr/bin/env db失败了,因为#它不是一个注释符号。我收到错误消息

db - Line 1 near ""#.//r" - " - syntax error

shell returned 26

有没有单行代码可以做到这一点?

答案1

使用 awk 作为 shebang 包装器:

#! /usr/bin/awk BEGIN{getline;cmd="db"}{print|cmd}END{exit(close(cmd))}

... "db" commands here ...

如果你的脚本是不是execve(2)应该直接通过但只能通过 shell (或通过类似命令)运行,find -exec你有更多的选择,包括使其可执行没有在它前面添加一个 shebang,并将其保留为该命令理解的任何语言的有效命令脚本db。这完全取决于该语言是什么。例如,如果该语言的注释行以//(如 C++ 中的)开头,则可以使用:

// 2>/dev/null; exec db "$0" "$@"

... "db" commands here ...

答案2

您可以编写一个 shell 脚本来删除 shebang 行(如果有),并将结果传递给db.将此脚本放在您的PATH.否则,您可能必须在 shebang 行中指定脚本的完整路径。使用此脚本作为您的parameterfile.

runparam如果第一行是 shebang 行,则删除它的示例脚本:

#!/bin/sh
awk 'FNR>1 || ! /^#!/' "$@" | db

例子parameterfile

#!/usr/bin/env runparam
filename
::
conditions

您可以将其运行为

./parameterfile

在这种情况下,脚本可以假设始终存在 shebang 行。

您还可以使用参数文件直接调用脚本,就像调用 一样db,但这没有任何优势。

runparam parameterfile
runparam parameterfile1 parameterfile2 [...]
runparam < parameterfile

如果您永远不会runparam使用不包含 shebang 行的文件进行调用,则可以使用tail而不是awk无条件删除第一行。这可能会更快。

#!/bin/sh
tail -n+2 | db

答案3

只需将其设为 shell 脚本即可。要么是这样的:

exec db << 'EOF'
filename
::
conditions
EOF

db(根据 shell 的不同,要么将此处文档的内容放入临时文件中,该临时文件将成为将要运行并在执行之前删除的进程的标准输入db,要么是带有 shell 进程通过其提供数据的管道)。

或者:

tail -n+2 < "$0" | db
filename
::
conditions

tail这里在和之间有一个管道(或者可能是带有 ksh93 的套接字对)db

或者:

exec < "$0"; IFS= read -r ignore; exec db
filename
::
conditions

这里db直接在脚本上打开 的 stdin,并用 跳过第一行read。这将是最有效率的。

相关内容