スクリプトから関数にスペースを含むオプション/引数/パラメータを渡す

スクリプトから関数にスペースを含むオプション/引数/パラメータを渡す

みなさん、こんにちは。よろしくお願いします。

フォーラムで自分の状況を検索しましたが、解決策を見つけることができませんでした。コマンド ラインで引数/オプション/パラメータを渡すスクリプトがあります。値の 1 つにスペースが含まれているため、二重引用符で囲みました。例を挙げたほうが簡単かもしれません。引数/オプション/パラメータの使い方についてはご容赦ください。

$:  ./test1.ksh -n -b -d "Home Videos"

私の問題は、変数を「ホーム ビデオ」に設定し、それを一緒に使用することです。私の例では、-d はディレクトリを指定するためのものです。すべてのディレクトリにスペースがあるわけではありませんが、私の場合はいくつかのディレクトリにスペースがあります。

これは、期待どおりに動作しないコードの例です。

#!/bin/ksh

Function1()
{
echo "Number of Args in Function1: $#"
echo "Function1 Args: $@"
SetArgs $*
}

SetArgs()
{
echo -e "\nNumber of Args in SetArgs: $#"
echo "SetArgs Args: $@"
while [ $# -gt 0 ]
do
  case $1 in
    -[dD])
    shift
    export DirectoryName=$1
    ;;
    -[nN])
    export Var1=No
    shift
    ;;
    -[bB])
    export Var2=Backup
    shift
    ;;
    *)
    shift
    ;;
  esac
done
Function2
}

Function2()
{
echo "Directory Name: ${DirectoryName}"
}

Function1 $*

これを実行すると、DirectoryName に Home Videos ではなく Home のみが取得されます。以下を参照してください。

 $ ./test1.ksh -n -b -d "Home Videos"
 Number of Args in Function1: 5
 Function1 Args: -n -b -d Home Videos

 Number of Args in SetArgs: 5
 SetArgs Args: -n -b -d Home Videos
 Var1 is set to:  No
 Var2 is set to:  Backup
 Directory Name: Home

私が期待していたが実現できなかったことは次のとおりです。

 $ ./test1.ksh -n -b -d "Home Videos"
 Number of Args in Function1: 4
 Function1 Args: -n -b -d "Home Videos"

 Number of Args in SetArgs: 4
 SetArgs Args: -n -b -d "Home Videos"
 Var1 is set to:  No
 Var2 is set to:  Backup
 Directory Name: Home Videos     <-- Without double quotes in the final usage.

これに関して何か助けていただければ大変ありがたいです... 二重引用符をエスケープしようとしましたが、成功しませんでした。

これを解決するのにご協力いただき、ありがとうございました。

よろしく、ダニエル

答え1

引用符の使用$*または$@引用符なし一度もない意味が通じます。

"$*"は、位置パラメータとの最初の文字(またはシェルによってはバイト)の連結であり$IFS"$@"位置パラメータのリストです。

引用符で囲まれていない場合も同様ですが、zsh他の引用符で囲まれていないパラメータ展開と同様に、split+glob(または を使用した空の削除のみ)の対象となります(シェルによっては、 が空の$*場合でも の引数を分離するものもあります$IFS)。

ここで引数のリストを渡しますそのまま関数に追加すると次のようになります:

SetArgs "$@"
[...]
Function1 "$@"

ksh88 では、$IFS正常に動作するためにはスペース文字 (デフォルトで含まれています) が含まれている必要があることに注意してください (Bourne シェルから継承されたバグで、ksh93 で修正されました)。

また、一部の実装(エミュレーションkshの古いバージョンなど)では、zshksh

export DirectoryName=$1

はsplit+glob呼び出しのケースです。Kornexportのようなシェルでシェルコードを評価できるコマンドの1つです。配列インデックスの算術評価を通じて)、 っていうことはコマンドインジェクションの脆弱性を回避するために変数を引用符で囲むことが重要となるケースの1つ

例:

$ (exec -a ksh zsh-4.0.1 -c 'export x=$a' ksh 'foo psvar[0`uname>&2`]')
Linux

[ $# -gt 0 ]は意味をなさない別の split+glob 呼び出しであることに注意してください(少なくとも のデフォルト値では問題になる可能性は低くなります$IFS)。

答え2

getopts組み込みのシェルコマンドを使用して引数を解析することを検討しましたか(たとえば、@Stéphane Chazelasが提案したように)このコメント)? そうすれば、こうした面倒な作業が大幅に軽減されます。

あなたの場合、関連するコードは次のようになります。

while getopts "nbd:" argname
do
    case "$argname" in
    n)  Var1="No" ;;
    b)  Var2="Backup" ;;
    d)  DirectoryName ="$OPTARG" ;;
    ?)  echo -e "usage is..."
        exit 1 ;;
    esac
done

関連情報