假设我有两个变量:
a="AAA"
b="BBB"
我从文件中读取了一个字符串。该字符串如下:
str='$a $b'
如何从第一个替换变量的字符串创建一个新字符串?
newstr="AAA BBB"
答案 0 :(得分:6)
eval
:好吧,由于eval
是 evil ,我们可以尝试通过在变量名中使用间接来实现这一点。
a="AAA"
b="BBB"
str='$a $b'
newstr=()
for cnt in $str ;do
[ "${cnt:0:1}" == '$' ] && cnt=${cnt:1} && cnt=${!cnt}
newstr+=($cnt)
done
newstr="${newstr[*]}"
echo $newstr
AAA BBB
另一次尝试:
var1="Hello"
var2="2015"
str='$var1 world! Happy new year $var2'
newstr=()
for cnt in $str ;do
[ "${cnt:0:1}" == '$' ] && cnt=${cnt:1} && cnt=${!cnt}
newstr+=($cnt)
done
newstr="${newstr[*]}"
echo $newstr
Hello world! Happy new year 2015
附录正如@ EtanReisner评论所指出的那样,如果你的字符串确实包含一些*
或其他 glob 消耗性蜇,那么你可能有使用set -f
来防止坏事:
cd /bin
var1="Hello"
var2="star"
var3="*"
str='$var1 this string contain a $var2 as $var3 *'
newstr=()
for cnt in $str ;do
[ "${cnt:0:1}" == '$' ] && cnt=${cnt:1} && cnt=${!cnt};
newstr+=("$cnt");
done;
newstr="${newstr[*]}"
echo "$newstr"
Hello this string contain a star as * bash bunzip2 busybox....zmore znew
echo ${#newstr}
1239
注意:我已在"
添加newstr+=("$cnt");
以阻止全局扩展,但似乎需要set -f
...
newstr=()
set -f
for cnt in $str ;do
[ "${cnt:0:1}" == '$' ] && cnt=${cnt:1} && cnt=${!cnt}
newstr+=("$cnt")
done
set +f
newstr="${newstr[*]}"
echo "$newstr"
Hello this string contain a star as * *
Nota 2:这远非一个完美的解决方案。对于示例,如果字符串确实包含ponctuation,则不会再次工作......示例:
str='$var1, this string contain a $var2 as $var3: *'
与前一次运行相同的变量将呈现:
' this string contain a star as *'
,因为${!var1,}
和${!var3:}
不存在。
$str
确实包含特殊字符:正如@godblessfq所说:
如果str包含换行符,我该如何进行替换并在输出中保留换行符?
所以这不是健全因为每个间接变量必须是所有特殊字符的第一个,最后一个或空格分隔!< / em>的
str=$'$var1 world!\n... 2nd line...'
var1=Hello
newstr=()
set -f
IFS=' ' read -d$'\377' -ra array <<<"$str"
for cnt in "${array[@]}";do
[ "${cnt:0:1}" == '$' ] && cnt=${cnt:1} && cnt=${!cnt}
newstr+=("$cnt")
done
set +f
newstr="${newstr[*]}"
echo "$newstr"
Hello world!
... 2nd line...
当<<<
内联字符串添加尾随换行符时,可以写入最后echo
命令:
echo "${newstr%$'\n'}"
答案 1 :(得分:2)
最简单的解决方案是使用eval
:
eval echo "$str"
要将其分配给变量,请使用命令替换:
replaced=$(eval echo "$str")