$ @のパラメーター展開はshシェルでサポートされていませんか?


8

私はAUに関する質問への回答を投稿ました$@が、shシェルでのパラメーター展開が機能しないことがわかりました。

<infile xargs -d'\n' sh -c 'echo "${@%%/*}"' _

しかし、それはで正常に動作しbashます。これはshシェルの予想される動作ですか、そこでシェルを拡張するにはどうすればよいですか?

さらに、-n1オプションでxargs一度にコマンドに渡すことができるのは1行だけであることはわかっていますが、sh展開できるかどうかに興味がありました$@

<infile xargs -d'\n' -n1 sh -c 'echo "${0%%/*}"'

infile 含む:

A1 /B1/C1
A 2/B2/C2
A3/B3/C3

回答:


12

うん、ダッシュはここでは役に立たないようです。厳密に言うと、POSIX${@%...}指定されていないため、これは問題ではありません。

以下の4種類のパラメーター拡張は、サブストリング処理を提供します。[...]パラメータが ' #'、 ' *'、または ' @'の場合、展開の結果は不定です。

奇妙なことですが、そのような展開が1つの位置パラメーターの終わりを変更すると、次のものは削除されるようです。しかし、それが実際に終了を変更しない場合はそうではありません:

$ dash -c 'set -- foo bar; printf "<%s>\n" "${@%o}";'
<fo>
$ dash -c 'set -- foo bar; printf "<%s>\n" "${@%x}";'
<foo>
<bar>
$ dash -c 'set -- foo bar doo; printf "<%s>\n" "${@%r}";'
<foo>
<ba>

Bash、ksh、およびZshはすべて、各位置パラメータを個別に処理"${@#...}"および"${@%...}"処理するように見えますが、これは便利なことのようです。

の明らかな回避策dashは、変更を一度に1つの引数にすることだと思います。

for x in "$@"; do echo "${x%%/*}"; done

価値があるのは、使用される接頭辞/接尾辞の削除拡張の動作$*もシェルによって異なることです。Bashとkshは最初にパラメーターを変更し、その後それらを結合するようですが、Zshとdashは最初にパラメーターを結合し、連結された文字列を変更します。

$ zsh -c 'set -- ax bx; printf "<%s>\n" "${*%%x*}";'
<a>
$ bash -c 'set -- ax bx; printf "<%s>\n" "${*%%x*}";'
<a b>

音はsh思っ$@ファイル全体のための単一のパラメータである(またはARG_MAXを超えた場合は、複数に壊れる)と唯一の引数の拡張を行います。
αғsнιη

1
また、pdkshとその誘導体はBad substitution、そのコードに関するエラーを表示することに注意してください。${*%pattern}次のようなものでは行動のいくつかのバリエーションを参照"$shell" -c 'printf "<%s>\n" "${*%x*}"' sh ax by
ステファンChazelas

1
@αғsнιη、それはそれほど単純ではありません。2番目の例では、展開により位置パラメータが個別の単語として残されています。そして、私はARG_MAXそれに入るとは思わない、その処理はシェルの内部にある。
ilkkachu
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.