Home > Software engineering >  how to assign variable to each value in quotes
how to assign variable to each value in quotes

Time:02-21

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
  • Related