我有一个变量$var_c
,它包含许多复杂的语法。我宁愿不需要多次重写,因为这很容易出错。但有时数据会发生变化。
#!/bin/bash
var_a="cat"
var_b="dog"
var_c="<div class="pet_a">$var_a</div><div class="pet_b">$var_b</div>"
echo $var_c
var_a="fish"
var_b="whale"
echo $var_c
这应该首先是<div class="pet_a">cat</div><div class="peg_b">dog</div>
,然后是<div class="pet_a">fish</div><div class="peg_b">whale</div>
,然而,在改变变量$var_a
和$var_b
之后,$var_c
不被更新。
我如何告诉BASH更新这个变量,而不必再次完全提供所有语法?
请改用Shell函数
在Bash中,赋值中的插值发生在赋值时。所以,你不能真的对一个变量做你想做的事情。相反,您应该使用shell函数。例如:
var_a="cat"
var_b="dog"
var_c () {
echo "<div class="pet_a">$var_a</div><div class="pet_b">$var_b</div>"
}
echo $(var_c)
# <div class="pet_a">cat</div><div class="pet_b">dog</div>
var_a="fish"
var_b="whale"
echo $(var_c)
# <div class="pet_a">fish</div><div class="pet_b">whale</div>
请注意,在这种情况下,您可以直接调用var_c
,而不是echo $(var_c)
,因为函数已经包含了一个echo语句。我在示例中有意使用它来维护当前的语义,并展示如何使用像变量一样的shell函数。
使用Printf格式字符串
在Bash中,赋值中的插值发生在赋值时。所以,你不能真的对一个变量做你想做的事情。解决这一问题的一种方法是使用格式字符串和printf内建。内置支持一个-v标志,上面写着:
-v var assign the output to shell variable VAR rather than
display it on the standard output
例如:
fmt="<div class="pet_a">%s</div><div class="pet_b">%s</div>"
var_a="cat"
var_b="dog"
printf -v var_c "$fmt" "$var_a" "$var_b"
echo "$var_c"
# <div class="pet_a">cat</div><div class="pet_b">dog</div>
var_a="fish"
var_b="whale"
printf -v var_c "$fmt" "$var_a" "$var_b"
echo "$var_c"
# <div class="pet_a">fish</div><div class="pet_b">whale</div>
func_c() {
echo "<div class="pet_a">$var_a</div><div class="pet_b">$var_b</div>"
}
var_a="cat"
var_b="dog"
echo "$(func_c)" # echoes '<div class="pet_a">cat</div><div class="pet_b">dog</div>'
var_a="fish"
var_b="whale"
echo "$(func_c)" # echoes '<div class="pet_a">fish</div><div class="pet_b">whale</div>'
请注意,执行函数时使用语法$(functionname)
(这实际上可以与任何命令一起使用),而不是仅使用变量的$variablename
。此外,您几乎应该总是将函数和变量引用都放在双引号中(就像我上面所做的那样)。此外,如果你真的只是打印结果,不要像我上面所做的那样使用echo "$(functionname)"
,只需直接使用functionname
。最后,让函数依赖于全局变量(var_a和var_b)通常是不好的做法——它们应该接收将要作为参数进行操作的数据:
func_c() {
# Usage: func_c var_a var_b
echo "<div class="pet_a">$1</div><div class="pet_b">$2</div>"
}
func_c "cat" "dog" # echoes '<div class="pet_a">cat</div><div class="pet_b">dog</div>'
func_c "fish" "whale" # echoes '<div class="pet_a">fish</div><div class="pet_b">whale</div>'
var_d="$(func_c "ferret" "weasel")" # sets var_d to '<div class="pet_a">ferret</div><div class="pet_b">weasel</div>'
(我在上面的例子中使用了比严格需要的更多的双引号,但在不需要的时候使用它们比在需要的时候不使用要好。)