현재 작성 중인 도구에는 다음 코드가 있습니다.
while [ $# -gt 0 ]; do
case "$1" in
--var1=*)
var1="${1#*=}"
;;
--var2=*)
var1="${1#*=}"
;;
--var3=*)
var1="${1#*=}"
;;
*)
printf "***************************\n
* Error: Invalid argument.*\n
***************************\n"
esac
shift
done
추가할 옵션이 많지만 그 중 5개는 배열로 저장해야 합니다. 따라서 셸에서 도구를 호출하면 다음과 같은 명령을 사용할 수 있습니다.
./tool --var1="2" --var1="3" --var1="4" --var1="5" --var2="6" --var3="7"
값을 var1
배열로 저장하는 방법은 무엇입니까? 그게 가능합니까? 그렇다면 어레이가 너무 많으면 효율성 측면에서 어레이를 처리하는 가장 좋은 방법은 무엇입니까?
답변1
Linux를 사용하는 경우( 유틸리티가 설치되어 util-linux
있거나 에서 ) 다음을 수행할 수 있습니다.getopt
busybox
declare -A opt_spec
var1=() var2=() var4=false
unset var3
opt_spec=(
[opt1:]='var1()' # opt with argument, array variable
[opt2:]='var2()' # ditto
[opt3:]='var3' # opt with argument, scalar variable
[opt4]='var4' # boolean opt without argument
)
parsed_opts=$(
IFS=,
getopt -o + -l "${!opt_spec[*]}" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=${o#--}
if ((${opt_spec[$o]+1})); then # opt without argument
eval "${opt_spec[$o]}=true"
else
o=$o:
case "${opt_spec[$o]}" in
(*'()') eval "${opt_spec[$o]%??}+=(\"\$1\")";;
(*) eval "${opt_spec[$o]}=\$1"
esac
shift
fi
esac
done
echo "var1: ${var1[@]}"
이 방법으로 스크립트를 호출할 수 있습니다.
my-script --opt1=foo --opt2 bar --opt4 -- whatever
--
getopt는 구문 분석, 처리 및 약어 작업을 대신 수행합니다.
$opt_spec
또는 연관 배열 정의에서 변수를 지정하는 대신 변수 유형을 사용할 수 있습니다 .
declare -A opt_spec
var1=() var2=() var4=false
unset var3
opt_spec=(
[opt1:]=var1 # opt with argument
[opt2:]=var2 # ditto
[opt3:]=var3 # ditto
[opt4]=var4 # boolean opt without argument
)
parsed_opts=$(
IFS=,
getopt -o + -l "${!opt_spec[*]}" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=${o#--}
if ((${opt_spec[$o]+1})); then # opt without argument
eval "${opt_spec[$o]}=true"
else
o=$o:
case $(declare -p "${opt_spec[$o]}" 2> /dev/null) in
("declare -a"*) eval "${opt_spec[$o]}+=(\"\$1\")";;
(*) eval "${opt_spec[$o]}=\$1"
esac
shift
fi
esac
done
echo "var1: ${var1[@]}"
다음과 같은 짧은 옵션을 추가할 수 있습니다.
declare -A long_opt_spec short_opt_spec
var1=() var2=() var4=false
unset var3
long_opt_spec=(
[opt1:]=var1 # opt with argument
[opt2:]=var2 # ditto
[opt3:]=var3 # ditto
[opt4]=var4 # boolean opt without argument
)
short_opt_spec=(
[a:]=var1
[b:]=var2
[c]=var3
[d]=var4
)
parsed_opts=$(
IFS=; short_opts="${!short_opt_spec[*]}"
IFS=,
getopt -o "+$short_opts" -l "${!long_opt_spec[*]}" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=${o#--}
if ((${long_opt_spec[$o]+1})); then # opt without argument
eval "${long_opt_spec[$o]}=true"
else
o=$o:
case $(declare -p "${long_opt_spec[$o]}" 2> /dev/null) in
("declare -a"*) eval "${long_opt_spec[$o]}+=(\"\$1\")";;
(*) eval "${long_opt_spec[$o]}=\$1"
esac
shift
fi;;
(-*)
o=${o#-}
if ((${short_opt_spec[$o]+1})); then # opt without argument
eval "${short_opt_spec[$o]}=true"
else
o=$o:
case $(declare -p "${short_opt_spec[$o]}" 2> /dev/null) in
("declare -a"*) eval "${short_opt_spec[$o]}+=(\"\$1\")";;
(*) eval "${short_opt_spec[$o]}=\$1"
esac
shift
fi
esac
done
echo "var1: ${var1[@]}"
답변2
나는 당신이 내 것을 살펴 보는 것이 좋습니다범용 셸 스크립트 GitHub:util_functions.sh. 거기에는 다음과 같은 함수가 표시됩니다.매개변수 가져오기. 옵션과 값을 연결하도록 설계되었습니다.
여기에 함수를 붙여넣을 뿐이지만 이 스크립트의 다른 여러 함수에 따라 달라집니다.
##########################
#
# Function name: getArgs
#
# Description:
# This function provides the getopts functionality
# while allowing the use of long operations and list of parameters.
# in the case of a list of arguments for only one option, this list
# will be returned as a single-space-separated list in one single string.
#
# Pre-reqs:
# None
#
# Output:
# GA_OPTION variable will hold the current option
# GA_VALUE variable will hold the value (or list of values) associated
# with the current option
#
# Usage:
# You have to source the function in order to be able to access the GA_OPTIONS
# and GA_VALUES variables
# . getArgs $*
#
####################
function getArgs {
# Variables to return the values out of the function
typeset -a GA_OPTIONS
typeset -a GA_VALUES
# Checking for number of arguments
if [[ -z $1 ]]
then
msgPrint -warning "No arguments found"
msgPrint -info "Please call this function as follows: . getArgs \$*"
exit 0
fi
# Grab the dash
dash=$(echo $1 | grep "-")
# Looking for short (-) or long (--) options
isOption=$(expr index "$dash" "-")
# Initialize the counter
counter=0
# Loop while there are arguments left
while [[ $# -gt 0 ]]
do
if [[ $dash && $isOption -eq 1 ]]
then
(( counter+=1 ))
GA_OPTIONS[$counter]=$1
shift
else
if [[ -z ${GA_VALUES[$counter]} ]]
then
GA_VALUES[$counter]=$1
else
GA_VALUES[$counter]="${GA_VALUES[$counter]} $1"
fi
shift
fi
dash=$(echo $1 | grep "-")
isOption=$(expr index "$dash" "-")
done
# Make the variables available to the main algorithm
export GA_OPTIONS
export GA_VALUES
msgPrint -debug "Please check the GA_OPTIONS and GA_VALUES arrays for options and arguments"
# Exit with success
return 0
}
보시다시피 이 특정 함수는 GA_OPTIONS 및 GA_VALUES를 내보냅니다. 유일한 조건은 값이 옵션 뒤에 공백으로 구분된 목록이어야 한다는 것입니다.
이 스크립트를 ./tool --var1 2 3 4 5 --var2="6" --var3="7"이라고 호출할 수 있습니다.
아니면 선호도에 맞게 비슷한 논리를 사용하세요.