简体   繁体   中英

Can I do a for loop over variables in the bash shell?

I'm learning the shell, and I want to be able to loop over some variables. I can't seem to find anywhere where anyone has done this so I'm not sure it's even possible.

Basically I just want to save myself trouble by using the same sed command on each of these variables. However the code obviously doesn't work. My question is, is it possible to loop over variables and if not how should I be doing this?

title="$(echo string1)"
artist="$(echo string2)"
album="$(echo string3)"

for arg in title artist album do
    $arg="$(echo "$arg" | sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g')"
done

here is the error:

line 12: syntax error near unexpected token `$arg="$(echo "$arg" | sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g')"'

Your problem isn't with the loop, it's with the assignment. The variable name needs to be literal in an assignment, ie you can write title=some_value but not $arg=some_value .

A portable way to assign to a variably-named variable is to use eval . You also need to obtain the value of $arg (not just the value of arg , which is $arg ), which again requires using eval .

new_value="$(eval printf %s \"\$$arg\" | …)"
eval $arg=\$new_value

Another way to assign to a variably-named variable that's specific to bash/ksh/zsh but won't work in plain sh is to use the typeset built-in. In bash, if you do this in a function, this makes the assignment local to the function. To obtain the value of the variably-named variable, you can use ${!arg} ; this is specific to bash.

typeset $arg="$(printf %s "${!arg}" | …)"

Other problems with your snippet:

  • title="$(echo string1)" is a complicated way to write title="string1" , which furthermore may mangle string1 if it contains backslashes or begins with - .
  • You need a command terminator ( ; or newline) before the do keyword.

If you're relying on bash/ksh/zsh, you can make the replacements inside the shell with the ${VARIABLE//PATTERN/REPLACEMENT} construct.

title="string1"
artist="string2"
album="string3"
for arg in title artist album; do
  eval value=\$$arg
  value=${value//&/&amp;}
  value=${value//</&lt;}
  value=${value//>/&gt;}
  eval $arg=\$value
done

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM