Is there a way to assign multiple variables from following string?
edit "admin1" edit "admin2" edit "admin3"
I would like to have
var1=admin1 var2=admin2 var3=admin3
Thanks.
CodePudding user response:
Try this:
read -r trash var1 trash var2 trash var3 <<< $(echo edit "admin1" edit "admin2" edit "admin3")
CodePudding user response:
There are a lot of ways to do this, but it really depends on how variable your data is, and how reliably you can parse your inputs. Given your example above, the following here-string and process substitution with the read builtin will work:
read var1 var2 var3 < \
<(sed -r 's/edit ?//g' <<< 'edit "admin1" edit "admin2" edit "admin3"')
echo $var1; echo $var2; echo $var3
This will correctly print:
"admin1"
"admin2"
"admin3"
You can also collect input as indexed or associative arrays, or use indirect variable expansions. However, if your real-world inputs are more complicated, your biggest challenge will be scanning for only the words in quotes, and will likely involve a lot of splitting and looping in one form or another.
CodePudding user response:
This Shellcheck-clean demonstration program uses the built-in regular expression support in Bash:
#! /bin/bash -p
edit_rx='edit[[:space:]] "([^"]*)"'
all_edits_rx="${edit_rx}[[:space:]] ${edit_rx}[[:space:]] ${edit_rx}"
teststr='edit "admin1" edit "admin2" edit "admin3"'
if [[ $teststr =~ $all_edits_rx ]]; then
var1=${BASH_REMATCH[1]}
var2=${BASH_REMATCH[2]}
var3=${BASH_REMATCH[3]}
else
printf "ERROR: '%s' does not match '%s'\\n" "$all_edits_rx" "$teststr" >&2
exit 1
fi
declare -p var1 var2 var3
An advantage of this approach is that it does a thorough check that the input has the expected format, thus minimizing the risk of Garbage in, garbage out.
If the number of quoted values in the string is not always 3 (and maybe even if it is always 3) it would be better to put the values in an array rather than in numbered variables. This Shellcheck-clean demonstration program shows one way to do it:
#! /bin/bash -p
editlist_rx='^edit[[:space:]] "([^"]*)"[[:space:]]*(.*)$'
teststr='edit "admin1" edit "admin2" edit "admin3" edit "admin4" edit "admin5"'
tmp=$teststr
vars=()
while [[ $tmp =~ $editlist_rx ]]; do
vars =( "${BASH_REMATCH[1]}" )
tmp=${BASH_REMATCH[2]}
done
if [[ -n $tmp ]]; then
printf "ERROR: failed match at '%s'\\n" "$tmp" >&2
exit 1
fi
for i in "${!vars[@]}"; do
printf 'vars[%d]=%q\n' "$i" "${vars[i]}"
done
It outputs:
vars[0]=admin1
vars[1]=admin2
vars[2]=admin3
vars[3]=admin4
vars[4]=admin5