我有一个列出数据库文件的程序。
它直接从 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
。这将是最有效率的。