Scripting

shebang 中的多個參數

  • July 1, 2021

我想知道是否存在通過 shebang 行 ( #!) 將多個選項傳遞給執行檔的通用方法。

我使用 NixOS,我編寫的任何腳本中 shebang 的第一部分通常是/usr/bin/env. 然後我遇到的問題是,之後的所有內容都被系統解釋為單個文件或目錄。

例如,假設我想編寫一個腳本以bash在 posix 模式下執行。寫shebang的天真方式是:

#!/usr/bin/env bash --posix

但嘗試執行生成的腳本會產生以下錯誤:

/usr/bin/env: ‘bash --posix’: No such file or directory

我知道這篇文章,但我想知道是否有更通用和更清潔的解決方案。


編輯:我知道對於Guile腳本,有一種方法可以實現我想要的,記錄在手冊的第 4.3.4 節中:

#!/usr/bin/env sh
exec guile -l fact -e '(@ (fac) main)' -s "$0" "$@"
!#

這裡的訣竅是第二行(以 開頭exec)被解釋為程式碼,sh但是,在#!!#塊中,作為註釋,因此被 Guile 解釋器忽略。

不可能將此方法推廣到任何解釋器嗎?


第二次編輯:玩了一會兒之後,似乎對於可以從中讀取其輸入的解釋器,stdin以下方法會起作用:

#!/usr/bin/env sh
sed '1,2d' "$0" | bash --verbose --posix /dev/stdin; exit;

不過,這可能不是最優的,因為該sh過程會一直持續到解釋器完成其工作。任何回饋或建議將不勝感激。

沒有通用的解決方案,至少如果您需要支持 Linux,則沒有,因為Linux 核心將 shebang 行中第一個“單詞”之後的所有內容視為單個參數

我不確定 NixOS 的限制是什麼,但通常我會把你的 shebang 寫成

#!/bin/bash --posix

或者,在可能的情況下,在腳本中設置選項

set -o posix

或者,您可以使用適當的 shell 呼叫讓腳本自行重新啟動:

#!/bin/sh -

if [ "$1" != "--really" ]; then exec bash --posix -- "$0" --really "$@"; fi

shift

# Processing continues

這種方法可以推廣到其他語言,只要您找到一種方法讓目標語言忽略前幾行(由 shell 解釋)。

GNU coreutilsenv從 8.30 版開始提供了一種解決方法,有關詳細資訊,請參閱unode答案。(這在 Debian 10 及更高版本、RHEL 8 及更高版本、Ubuntu 19.04 及更高版本等中可用。)

雖然不完全可移植,但從 coreutils 8.30 開始,根據其文件,您將能夠使用:

#!/usr/bin/env -S command arg1 arg2 ...

所以給出:

$ cat test.sh
#!/usr/bin/env -S showargs here 'is another' long arg -e "this and that " too

你會得到:

% ./test.sh 
$0 is '/usr/local/bin/showargs'
$1 is 'here'
$2 is 'is another'
$3 is 'long'
$4 is 'arg'
$5 is '-e'
$6 is 'this and that '
$7 is 'too'
$8 is './test.sh'

如果你好奇的話showargs是:

#!/usr/bin/env sh
echo "\$0 is '$0'"

i=1
for arg in "$@"; do
   echo "\$$i is '$arg'"
   i=$((i+1))
done

引用自:https://unix.stackexchange.com/questions/399690