Shebangで `/usr/bin/env sed -f`を使用する方法は?

Shebangで `/usr/bin/env sed -f`を使用する方法は?

/usr/bin/env sed -f端末に入力すると有効です。

でもシャバンだと思ったら、

#!/usr/bin/env sed -f 
s/a/b/

スクリプトは実行されません。

/usr/bin/env: sed -f: No such file or directory

私はそれが-fに関連していると思います。しかし、この問題をどのように解決するのですか?

ベストアンサー1

#!1行に複数のパラメータを含めることはできません。。これは、フルパスと1つの引数(たとえば、#!/bin/sed -fまたは#!/usr/bin/sed -f)しかないか、#!/usr/bin/envインタプリタの引数がないことを意味します。

移植可能なスクリプトを取得する回避策は、シェルラッパーを使用#!/bin/shしてsedスクリプトをコマンドライン引数として渡すことです。これはPOSIX承認ではありませんが(移植性のために複数の命令スクリプトは-e各命令に対して別々のパラメータを作成する必要があります)、多くの実装で機能します。

#!/bin/sh
exec sed '
s/a/b/
' "$@"

長いスクリプトの場合は、heredocを使用する方が便利です。 Heredocの1つの利点は、内部単一引用符(存在する場合)を引用する必要がないことです。 1つの主な欠点は、スクリプトが標準入力を介してsedに供給されることです。これは2つの迷惑な結果を引き起こします。 sed の一部のバージョンでは-f /dev/stdinこれを代わりに要求しますが-f -、これは移植性に問題となります。さらに、標準入力はデータではなくスクリプトであるため、スクリプトはフィルタとして機能できません。

#!/bin/sh
exec sed -f - -- "$@" <<'EOF'
s/a/b/
EOF

ここでの文書化の欠点は、効果的な使用で補完することができますcat。これはスクリプト全体をコマンドラインに戻すので、POSIXと互換性がありませんが、実際には移植性に優れています。

#!/bin/sh
exec sed "$(cat <<'EOF')" -- "$@"
s/a/b/
EOF

別の解決策は、shとsedで解析できるスクリプトを書くことです。移植性に優れ、かなり効率的ですが、少し醜いです。

#! /bin/sh
b ()
{
x
}
i\
f true; then exec sed -f "$0" "$@"; fi
: ()
# sed script starts here
s/a/b/

説明する:

  • shの下:関数bの構文が正しい限り(特に空の関数はありません)という関数を定義します。内容は重要ではありません。次にtrue(つまり常に)の場合、sedスクリプトは実行されます。
  • sedから:()ラベルに分岐し、正しい形式の入力を入力します。それからi常にスキップするので、何の効果もないコマンドがあります。最後に、タグがあり、()その後にスクリプトの有用な部分があります。
  • GNU sed、BusyBox、OpenBSDでテストされました。 (GNU sedでは簡単なものを使用できますが、OpenBSD sedはスキップするのが面倒です)。

おすすめ記事