【问题标题】:Can I do a for loop over variables in the bash shell?我可以在 bash shell 中对变量进行 for 循环吗?
【发布时间】:2011-06-18 07:59:12
【问题描述】:

我正在学习 shell,我希望能够循环一些变量。我似乎找不到任何人这样做的地方,所以我不确定这是否可能。

基本上,我只是想通过对每个变量使用相同的 sed 命令来省去麻烦。但是代码显然不起作用。我的问题是,是否可以循环变量,如果不能,我应该怎么做?

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

这是错误:

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

【问题讨论】:

  • 运行代码时出现什么错误? (假设您指的是语法突出显示尚未向您指出的内容......)
  • 解决此类问题的另一种常见方法是:

标签: linux shell variables


【解决方案1】:

您的问题不在于循环,而在于分配。变量名在赋值中必须是文字,即你可以写title=some_value,但不能写$arg=some_value

分配给可变名称变量的一种可移植方式是使用eval。还需要获取$arg的值(不仅仅是arg的值,也就是$arg),同样需要使用eval

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

另一种分配给特定于 bash/ksh/zsh 但不适用于普通 sh 的变量命名变量的方法是使用内置的 typeset。在 bash 中,如果您在函数中执行此操作,这会使赋值成为函数的局部变量。获取变量名变量的值,可以使用${!arg};这是特定于 bash 的。

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

您的 sn-p 的其他问题:

  • title="$(echo string1)" 是写 title="string1" 的复杂方式,如果 string1 包含反斜杠或以 - 开头,则可能会混淆。
  • do 关键字之前需要一个命令终止符(; 或换行符)。

如果您依赖 bash/ksh/zsh,则可以使用 ${VARIABLE//PATTERN/REPLACEMENT} 构造在 shell 内进行替换。

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

【讨论】:

  • 这太棒了。我试过了,实际上它并没有奏效(我正在尝试便携式路线)。这是我想出的:new_value="$(eval printf %s \"\$$arg\" | sed -e 's/&amp;/\\&amp;amp;/g' -e 's/&lt;/\\&amp;lt;/g' -e 's/&gt;/\\&amp;gt;/g')" eval arg=\$new_value 我必须在 printf 语句中添加第二个 $,否则 new_value 将等于“title”“album”或“artist”。我还从第二个 eval 语句中删除了 $ 或者等于“title”等。哦,为了好奇,为什么在第二行的 new_value 之前必须有一个 \$ 而不是 $?
  • @Dennis:抱歉,printf 通话中缺少的$ 是一个错字。其他的我没看出有什么问题,你说的是哪一个?在eval $arg=\$new_value 中,要评估的字符串类似于title=$new_value,它将new_value 的值分配给变量title。如果您写了eval $arg=$new_value,则要评估的字符串将是例如title=Apostrophe ('):新值将用作 shell 代码,而不是文字字符串。
猜你喜欢
  • 2020-02-05
  • 1970-01-01
  • 2015-05-22
  • 2015-06-27
  • 2012-06-28
  • 2018-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多