Can I do a for loop over variables in the bash she

2019-07-13 06:14发布

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')"'

1条回答
孤傲高冷的网名
2楼-- · 2019-07-13 06:54

Your problem isn't with the loop, it's with the assignment. The variable name needs to be literal in an assignment, i.e. 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
查看更多
登录 后发表回答