23

さまざまな位置パラメーターを使用できるスクリプトがあるとし#!/bin/shます。その中には、スペース、どちらか/両方の種類の引用符などが含まれる場合があります。反復"$@"し、引数ごとに何らかの方法ですぐに処理するか、後で保存します。execスクリプトの最後で、(おそらく) 別のプロセスを起動し、これらのパラメーターの一部をすべての特殊文字をそのままにして渡したいと思います。

パラメータを処理していなければothercmd "$@"問題なく動作しますが、いくつかのパラメータを取り出して少し処理する必要があります。

Bash を仮定できれば、後で使用printf %qできる引数の引用バージョンを計算するために使用できますevalが、これはたとえば Ubuntu の Dash ( /bin/sh) では機能しません。

printf %qスクリプトにコピーできる関数として、ビルトインおよびPOSIX定義のユーティリティのみを使用して、プレーンなBourneシェルスクリプトで記述できるものと同等のものはありますか?

たとえば、ls引数を逆の順序で実行しようとするスクリプト:

#!/bin/sh
args=
for arg in "$@"
do
    args="'$arg' $args"
done
eval "ls $args"

多くの場合に機能します:

$ ./handle goodbye "cruel world"
ls: cannot access cruel world: No such file or directory
ls: cannot access goodbye: No such file or directory

'が使用される場合ではありません。

$ ./handle goodbye "cruel'st world"
./handle: 1: eval: Syntax error: Unterminated quoted string

以下は問題なく動作しますが、Bash に依存しています。

#!/bin/bash
args=
for arg in "$@"
do
    printf -v argq '%q' "$arg"
    args="$argq $args"
done
eval "ls $args"
4

5 に答える 5

2

これはPOSIXだと思います。for ループを展開した後にクリアすることで機能$@しますが、 を使用して繰り返し (逆に) バックアップを構築できるように 1 回だけsetです。

flag=0
for i in "$@"; do
    [ "$flag" -eq 0 ] && shift $#
    set -- "$i" "$@"
    flag=1
done

echo "$@"   # To see that "$@" has indeed been reversed
ls "$@"

set -- "$arg" "$@"引数を逆にすることは単なる例であると認識していますが、このトリックをまたはset -- "$@" "$arg"他の状況で使用できる場合があります。

そうです、ormaaj の Push を (不十分に) 再実装しただけかもしれません。

于 2012-08-28T15:28:55.137 に答える
1

以下は、スペース、両方の種類の引用符、その他のさまざまなメタ文字、埋め込み改行など、これまでに投げたすべてのもので機能するようです。

#!/bin/sh
quote() {
    echo "$1" | sed "s/'/'\"'\"'/g"
}
args=
for arg in "$@"
do
    argq="'"`quote "$arg"`"'"
    args="$argq $args"
done
eval "ls $args"
于 2012-08-28T15:35:14.930 に答える
1

を押します。例については、readme を参照してください。

于 2012-08-28T15:08:38.033 に答える