我希望能够调用一个函数,并保留函数对字符串执行的所有修改。
例如: 我试过这个剧本
#!/bin/bash
change_string() {
var=$1
var+=",Hello2"
echo "Function: $var"
}
myString="Hello1"
change_string $myString
echo "Main: $myString"
这将打印出来:
Function: Hello1,Hello2
Main: Hello1
有没有办法在函数调用中更改$ myString,但是将这些更改保留在main中?我想我可能错过了与传递引用相关的bash中的一些内容?
答案 0 :(得分:3)
现代版本的bash提供" nameref"支持,允许变量引用另一个变量。
#!/usr/bin/env bash
case $BASH_VERSION in
[123].*|4.[012].*) echo "This needs bash 4.3 or newer" >&2; exit 1;;
esac
# local variable is prefixed because this will fail if we're passed a variable name we use
# internally; prefixing the local names makes such collisions unlikely.
change_string() {
# make change_string__var an alias for the variable named in our argument
declare -n change_string__var=$1
# append to that variable
change_string__var+=",Hello2"
# ...and log the new value, 'cuz that's what the original code did.
echo "Function: $change_string__var"
}
myString="Hello1"
change_string myString ## pass variable **name**, not variable value
echo "Main: $myString"
或者,作为一种不那么新奇的方法,可以使用${!var}
进行间接引用,printf -v
进行间接分配。
#!/usr/bin/env bash
change_string() {
# Store the variable name in a regular local variable
local change_string__var=$1
# Use ${!var} to get the value of the variable thus named
local change_string__val=${!change_string__var}
# Use ''printf -v varname ...'' to assign a new value
printf -v "$change_string__var" %s "${change_string__val},Hello2"
}
myString="Hello1"
change_string myString
echo "Main: $myString"
答案 1 :(得分:1)
您必须将变量的名称传递给您的函数,而不是其值。一旦你这样做,有几个选择。
最简单的可能是使用nameref(需要bash
4.3或更高版本):
change_string() {
declare -n var=$1
var+=",Hello2"
}
$ foo="Hello1"
$ change_string foo
$ echo "$foo"
Hello1,Hello2
在引入namerefs之前,您可以使用declare -g
,这需要bash
4.2或更高版本:
change_string () {
var=$1
old_val=${!var}
declare -g "$1=${old_val},Hello2"
}
在4.2之前,你几乎陷入使用eval
并且用手指交叉,你没有被代码注入攻击所困扰。
change_string () {
var=$1
eval "$1=\$$1,Hello2"
}
但这些方法都不是完全万无一失的;请参阅Bash FAQ 048的this section。我的建议是尽量避免需要这样的功能。
答案 2 :(得分:0)
declare
是具有动态范围的罕见语言之一(与通常的词法范围不同)。这意味着函数正在从定义它们的最后一个作用域中访问变量(可能是带有local
或#!/bin/bash
fun() {
x="newval"
}
x=start
echo "$x"
fun
echo "$x"
的赋值或声明。
例如:
start
newval
将打印:
x
这个简单的例子看起来像#!/bin/bash
change_string() {
myString+=",Hello2"
}
myString="Hello1"
change_string $myString
echo "Main: $myString"
是一个简单的全局变量,但它不止于此(范围是动态嵌套的,总是访问最后/前一个范围)。
因此,如果您想更改函数中的变量,只需更改它。
declare -g
您甚至可以通过引用"更改变量"如果您传递变量的名称,则使用varname
设置(在外部范围内)通过将文本附加到当前值(通过间接扩展访问),我们知道其名称(change_string() {
varname="$1"
declare -g "$varname"="${!varname},Hello2"
}
myString="Hello1"
change_string myString
# myString is now "Hello1,Hello2"
)的变量的值:
Message