원격 서버에 배포할 파일을 선택하기 위해 사용자의 입력(옵션 1, 2, 3 등)을 받아들이는 스크립트가 있습니다. 사용자가 이 스크립트를 여러 번 실행하는 대신 여러 옵션(예: 2,3)을 입력할 수 있기를 바랍니다. 이러한 항목에는 변수에 텍스트가 추가되어 기본 함수에서 참조됩니다.
이를 합산하고 입력을 합계와 일치시키려고 시도했지만 이 목록에 넣을 아티팩트가 많은 경우 옵션 5는 한 가지를 배포하고 옵션 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[@]}"