/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はスキップするのが面倒です)。