73 lines
1.5 KiB
Bash
73 lines
1.5 KiB
Bash
set -u
|
|
set -e
|
|
|
|
# ParseArgs will parse a string that contains quoted strings the same
|
|
# as bash does (same as most other *nix shells do). This is secure in
|
|
# the sense that it doesn't do any executing or interpreting. However,
|
|
# it also doesn't do any escaping, so you shouldn't pass these strings
|
|
# to shells without escaping them.
|
|
parseargs() {
|
|
notquote="-"
|
|
str=$1
|
|
declare -a args=()
|
|
s=""
|
|
|
|
# Strip leading space, then trailing space, then end with space.
|
|
str="${str## }"
|
|
str="${str%% }"
|
|
str+=" "
|
|
|
|
last_quote="${notquote}"
|
|
is_space=""
|
|
n=$(( ${#str} - 1 ))
|
|
|
|
for ((i=0;i<=$n;i+=1)); do
|
|
c="${str:$i:1}"
|
|
|
|
# If we're ending a quote, break out and skip this character
|
|
if [ "$c" == "$last_quote" ]; then
|
|
last_quote=$notquote
|
|
continue
|
|
fi
|
|
|
|
# If we're in a quote, count this character
|
|
if [ "$last_quote" != "$notquote" ]; then
|
|
s+=$c
|
|
continue
|
|
fi
|
|
|
|
# If we encounter a quote, enter it and skip this character
|
|
if [ "$c" == "'" ] || [ "$c" == '"' ]; then
|
|
is_space=""
|
|
last_quote=$c
|
|
continue
|
|
fi
|
|
|
|
# If it's a space, store the string
|
|
re="[[:space:]]+" # must be used as a var, not a literal
|
|
if [[ $c =~ $re ]]; then
|
|
if [ "0" == "$i" ] || [ -n "$is_space" ]; then
|
|
echo continue $i $is_space
|
|
continue
|
|
fi
|
|
is_space="true"
|
|
args+=("$s")
|
|
s=""
|
|
continue
|
|
fi
|
|
|
|
is_space=""
|
|
s+="$c"
|
|
done
|
|
|
|
if [ "$last_quote" != "$notquote" ]; then
|
|
>&2 echo "error: quote not terminated"
|
|
return 1
|
|
fi
|
|
|
|
for arg in "${args[@]}"; do
|
|
echo "$arg"
|
|
done
|
|
return 0
|
|
}
|