私が作業しているスクリプトに新しく追加されたものでは、zshがコマンドの次のフラグに達するまで、フラグに関連するパラメータを繰り返したいと思います。たとえば、ユーザーが次のように入力した場合:
datt -p Package1 Package2 Package3 --build
スクリプトはPackage1
、Package2
およびPackage3
それぞれを配列の位置に割り当てる必要があります。私の思考プロセスは次のとおりです。
packages=()
for i in "$@"; do
packages+=("$i")
done
だから私の質問は、コマンドラインの次のフラグが表示されるまでこのループを続行するスクリプトをどのように書くのですか?質問の冒頭に示されているコマンド()を使用して、datt -p Package1 Package2 Package3 --build
forループが--build
パッケージ名をキャプチャするのを防ぎ、配列への文字列の追加を停止するにはどうすればよいですかPackageN
?
答え1
パラメータを正しく解析するのは面倒です。私はあなたが使用することをお勧めします選択を受ける(1)。ここで同じフラグを複数回指定できます。
datt -p Package1 -p Package2 -p Package3 --build
何らかの理由でフラグを再利用できない場合(何かはわかりませんが...)、パラメータを個々の項目に渡してスペースを区切ることもできます。
datt -p "Package1 Package2 Package3" --build
答え2
shift
この解析を実行するには、配列が空になるまでwhileループを使用する方が簡単です。
packages=()
while (($#)); do
case $1 in
-p)
while shift; [[ $1 != -* ]]; do
packages+=($1)
done
…
esac
shift
done
あなたはそれを使用することができますi
下付き文字記号内部ループを実行して、次のオプションを見つけます。$array[(i)PATTERN]
は最初に一致する要素のインデックスですPATTERN
。インデックスは1から始まるので、1を引いて残りの要素数を取得します。一致するものがない場合、PATTERN
値は最後の要素のインデックスに1を加えた値なので、この場合もこのようなコードは機能します。
packages=()
while (($#)); do
case $1 in
-p) ((n = $@[(i)-*] - 1)); packages+=($@[1,$n]); shift $n;;
…
esac
shift
done
説明する構文は非標準です。このため、私はこれをしないことをお勧めします。ユーザーに混乱を与える可能性があるためです。通常datt -p Package1 Package2 Package3 --build
同じことをしますdatt -p Package1 Package2 --build Package3
。
答え3
一般的に最も賢明な方法は、ループ内のすべてのオプションを見て、コンテンツを正しい場所に配置することです。通常、パラメータ解析ループでは処理されませんが、オプションの順序が重要な場合は意味があります。
たとえば、次のループ(Bashまたはzshの場合)は次のようになります。
#!/usr/bin/zsh
packages=()
while [ "$#" -gt 0 ]; do
case $1 in
-p) echo "p option seen...";;
--build) echo "--build option seen after ${#packages[@]} packages...";;
*) echo "adding package '$1'";
packages+=("$1");;
esac
shift;
done
typeset -p packages;
減らす:
$ zsh dattest.sh -p foo bar doo --build
p option seen...
adding package 'foo'
adding package 'bar'
adding package 'doo'
--build option seen after 3 packages...
typeset -a packages=( foo bar doo )