リモートサーバーに展開するファイルを選択するためにユーザーの入力(オプション1、2、3など)を受け入れるスクリプトがあります。ユーザーがこのスクリプトを複数回実行するのではなく、複数のオプション(例:2,3)を入力できることを願っています。これらの項目には変数にテキストが追加され、基本関数で参照されます。
これを合計して入力を合計と一致させようとしましたが、このリストに入れる成果物が多い場合、オプション5は1つを展開し、オプション2,3は異なる配布を行いますが、一緒に使用するとオプション5と同じコンテンツを配布します。それは受け入れられません。
たとえば、これが私が現在設定したものです。ユーザーが入力した文字列を一致させ(スペースがある場合は削除した後)、そのオプションを実行します。これは2〜3つのアーティファクトにのみ適していますが、リストが長くなると選択肢が指数関数的に増加します。
#!/bin/sh
export alltags="all"
export tag1="artifact1"
export tag2="artifact2"
export tag3="artifact3"
deployment_tag=""
function updateArtifacts
{
cp -r /path/to/artifact/artifact.zip --tags "\"${deployment_tag}"\"
}
echo "Enter the number of the artifacts you would like to deploy"
"1. artifact1"
"2. artifact2"
"3. artifact3"
read -p " " num
trimNum=`echo $num | sed 's/ //g'`
if [ "$trimNum" == "1" ]; then
$deployment_tag+="$alltags"
echo "Updating all artifacts"
updateArtifacts
elif [ "$trimNum" == "2" ]; then
$deployment_tag+="$tag1"
echo "Updating artifact 1"
updateArtifacts
elif [ "$trimNum" == "2,3" ]; then
$deployment_tag+="$tag1,$tag2"
echo "Updating artifact 1 and 2"
updateArtifacts
else
echo "aborted, please enter a valid selection"
fi
オプションが欠落していることはわかっていますが、これは単純な例を提供するためのものです。内容が長いことが分かっており、ご意見をお寄せいただきありがとうございます。
答え1
以下は、配列を使用してこれを行う方法の例です。オプションで、コマンドラインから引数を取得します。引数が指定されない場合は、成果物ラベルの入力を求められます。
case
すべてのラベルを配列に入れる必要はないことがわかったので、私はこのステートメントを使用しません。
#!/bin/bash
# dup stdout so we can print prompts etc in the ask function
# anything printed to >&3 will go to the terminal (i.e. original stdout)
# anything printed to stdout will be part of the function's return value
exec 3>&1
tags=( all
artifact1 artifact2 artifact3
artifact4 artifact5 artifact6
artifact7 artifact8 artifact9
artifact10 artifact11 artifact12
artifact13 artifact14 artifact15
)
declare -a deployment_tags
declare -a nums
# comment out or set to zero to disable debugging
debug=1
[ "$debug" = 1 ] && declare -p tags deployment_tags nums
###
### functions
###
print_choices() {
i=1
while [ "$i" -lt "${#tags[@]}" ] ; do
# one per line
#printf '%i. %s\n' "$i" "${tags[$i]}" >&3
#let i=i+1
# or three per line
for j in 0 1 2; do
[ -n "${tags[$i]}" ] && printf '%2i. %-12s\t' "$i" "${tags[$i]}" >&3
let i=i+1
done
printf "\n" >&3
done
}
usage() {
echo "Usage: $(basename "$0") [n...]"
echo
print_choices
echo "Choose 1 or more, separated by spaces or commas, or 0 for all of the above"
exit 1;
}
ask() {
echo "Enter the number of the artifacts you would like to deploy:" >&3
print_choices
echo "Choose 1 or more, separated by spaces or commas, 0 for all, or q to quit" >&3
until [[ "$num" =~ ^[[:space:]0-9,qQ]+$ ]] ; do
read -r -p "Choose: " num >&3
[[ $num =~ [qQ] ]] && return 1
# split into nums array. if num contains zero ("all"), remove
# all other choices as they're already included in "all"
nums=( $(printf '%s' "$num" | sed -e 's/.*0.*/0/; s/,/ /g') )
# if any of the numbers provided didn't correspond to a valid
# tag, ask again
for i in "${nums[@]}" ; do
[ -z "${tags[$i]}" ] && echo "Invalid choice $i" >&3 && num=""
done
done
echo "${nums[@]}"
}
updateArtifacts() {
# WTF is the `--tags` argument to `cp`???
# echo it because it's bogus
echo cp -r /path/to/artifact/artifact.zip --tags "$@"
# this function should do something useful with "$@".
}
###
### main code
###
# get the args from the command line, or ask for them if missing.
if [ -n "$*" ] ; then
# only digits separated by commas or spaces allowed
[[ "$*" =~ ^[[:space:]0-9,]+$ ]] || usage
# split into nums array. if num contains zero ("all"), remove
# all other choices as they're already included in "all"
nums=( $(printf '%s' "$*" | sed -e 's/.*0.*/0/; s/,/ /g') )
else
nums=( $(ask) )
[ "$?" != 0 ] && echo "Quitting..." && exit 0
fi
[ "$debug" = 1 ] && declare -p nums
# get nums choices into deployment_tags array
for i in "${nums[@]}" ; do
[ -z "${tags[$i]}" ] && echo "Error: tag $i does not exist!" && exit 2
deployment_tags+=("${tags[$i]}")
done
[ "$debug" = 1 ] && declare -p deployment_tags
updateArtifacts "${deployment_tags[@]}"