我正在学习shell,我希望能够遍历一些变量。我似乎找不到任何人做过这个的地方,所以我不确定它是否可能。
基本上我只想通过对每个变量使用相同的sed命令来省去自己的麻烦。但是代码显然不起作用。我的问题是,是否可以循环变量,如果不是,我该怎么做?
title="$(echo string1)"
artist="$(echo string2)"
album="$(echo string3)"
for arg in title artist album do
$arg="$(echo "$arg" | sed -e 's/&/\&/g' -e 's/</\</g' -e 's/>/\>/g')"
done
这是错误:
line 12: syntax error near unexpected token `$arg="$(echo "$arg" | sed -e 's/&/\&/g' -e 's/</\</g' -e 's/>/\>/g')"'
答案 0 :(得分:5)
问题不在于循环,而在于分配。变量名在分配中必须是文字的,即您可以写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}" | …)"
您的代码段的其他问题:
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//&/&}
value=${value//</<}
value=${value//>/>}
eval $arg=\$value
done