スペースとワイルドカードを含むパラメータ渡しの問題

スペースとワイルドカードを含むパラメータ渡しの問題

パラメーターにワイルドカードおよび/またはスペースが含まれている場合(該当するパラメーターがオプションの場合)、パラメーターを渡すのに問題があります。これは非常に抽象的に聞こえるので、簡単な例を見てみましょう。次のシェルスクリプトにはsome_command.sh2つまたは3つのパラメータが必要です。最初の引数はコマンドラインスイッチでなければならず、2番目の引数はオプションであり、存在する場合は形式のコマンドラインスイッチでなければならず、最後の引数は必須であり、何でも構いません--NAME=VALUE

#!/bin/bash
# This is file some_command.sh
# Synopsis:
# some_command.sh --switch1=val1 [--switch2=val2] arg
echo "switch1: $1"
shift
if [[ "$1" == --*=* ]]
then
  echo "switch2 ($1) detected"
  shift
fi
echo argument is ${1:?argument missing}

some_command.sh次のような他のスクリプトを介して呼び出すとしますcaller.sh

#!/bin/bash
# This is file caller.sh
if [[ ${1:-x} == x ]]
then
  switch="--abc=long argument"
else
  switch=""
fi
some_command.sh "--exclude=*~" "$switch" arg

引用を参照してください。引用符は、--excludeシェル内のワイルドカード式を拡張できないため、必要であり、スペースを含む"$switch"テキスト$switchを含めることができ、引数をスペースに分割できないために必要です。

意図は、私たちが実行すると、caller.sh x次のような結果が生じるはずです。

some_command.sh "--exclude=*~" "--abc=long argument"  arg

たとえば、私たちが実行した場合は、caller.sh y次のようになります。

some_command.sh "--exclude=*~" arg

私がcaller.shここで提供するものは実際にいいえ後者の場合は実行されるのでうまくいきます。

some_command.sh "--exclude*~" "" arg

これは正確ではありません。

コマンドの前にプレフィックスを付けてみましたeval。これは問題を解決しますが、$switch二重引用符も削除され、"--exclude"ワイルドカードはシェルで評価されます。

eval引き続き追加の引用レベル(例:)が利用可能になりそうですが、"\"--exclude*~\""これは悪い解決策です。誰もがこれを行うよりクリーンな方法があるかどうか疑問に思います。

私がなぜこの質問をするのか疑問に思った場合:zipファイル名のスペースを処理する必要があるスクリプトを書いている間、私は偶然この質問を見つけました。

しかし、上記のように、およびbashで問題が発生しますzsh。私はまた、シェルの1つだけが機能する賢い解決策にも興味があります。

ベストアンサー1

配列は可変数の引数に拡張されるので、使用してください。

#! /bin/bash -
# This is file caller.bash
switch=()
if [[ ${1-x} == x ]]
then
  switch=("--abc=long argument")
fi
some_command.sh "--exclude=*~" "${switch[@]}" arg

または、次の構文を使用できます${var+...}

#! /bin/sh -
# This is file caller.sh
unset switch
if [ "${1-x}" = x ]
then
  switch="--abc=long argument"
fi
some_command.sh "--exclude=*~" ${switch+"$switch"} arg

zshを使用すると、次のことができます。

#! /bin/zsh -
switch=
if [ "${1-x}" = x ]
then
  switch="--abc=long argument"
fi
some_command.sh "--exclude=*~" $switch arg

zshしないでください分割+グローバルパラメータ拡張ではそうではありません。空の除去これがあなたが望むものです。

おすすめ記事