Причина в том, что вы использовали метод readlines (), который возвращает список строк в файле. Таким образом, в вашем списке текста может быть какой-то метод, который добавляет {и} к каждому элементу списка
Я нашел способ сделать это, но я не уверен, насколько корректный это:
Newfun()
{
local var1="$1"
eval $var1=2
# or can do eval $1=2 if no local var
}
var=1
echo var is $var # $var = 1
newfun 'var' # pass the name of the variable…
echo now var is $var # $var = 2
, Таким образом, мы передаем имя переменной в противоположность значению и затем используем оценку
Bash не имеет ничего как ссылки встроенным в него, таким образом, в основном единственный способ, которым Вы смогли бы сделать то, что Вы хотите, состоит в том, чтобы передать функцию название глобальной переменной, которую Вы хотите, чтобы это изменило. И даже затем Вам будет нужно eval
оператор:
boo() {
eval ${1}="new"
}
SOME_VAR="old"
echo $SOME_VAR # old
boo "SOME_VAR"
echo $SOME_VAR # new
я не думаю, что можно использовать косвенные ссылки здесь, потому что Bash автоматически получает доступ к значению переменной, имя которой хранится в косвенной ссылке. Это не дает Вам шанс установить его.
Оценка никогда не должна использоваться на строке, которую пользователь может установить потому что его опасное. Что-то как "строка; комната-rf ~" будет плоха. Так обычно его лучшее для нахождения решений, где Вы не должны волноваться об этом.
Однако оценка будет необходима для установки переданных переменных как отмеченный комментарий.
$ y=four
$ four=4
$ echo ${!y}
4
$ foo() { x=$1; echo ${!x}; }
$ foo four
4
Используйте вспомогательную функцию upvar
:
# Assign variable one scope above the caller.
# Usage: local "$1" && upvar $1 value [value ...]
# Param: $1 Variable name to assign value to
# Param: $* Value(s) to assign. If multiple values, an array is
# assigned, otherwise a single value is assigned.
# NOTE: For assigning multiple variables, use 'upvars'. Do NOT
# use multiple 'upvar' calls, since one 'upvar' call might
# reassign a variable to be used by another 'upvar' call.
# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
upvar() {
if unset -v "$1"; then # Unset & validate varname
if (( $# == 2 )); then
eval $1=\"\$2\" # Return single value
else
eval $1=\(\"\${@:2}\"\) # Return array
fi
fi
}
И используйте ее вот так из Newfun ()
:
local "$1" && upvar $1 new
Для возврата нескольких переменных используйте другую вспомогательную функцию upvars
. Это позволяет передавать несколько переменных в одном вызове, что позволяет избежать возможных конфликтов, если один вызов upvar
изменяет переменную, используемую в другом последующем вызове upvar
.
См .: http://www.fvue.nl/wiki/Bash:_Passing_variables_by_reference для вспомогательной функции upvars
и другой информации.
Проблема с:
eval $1=new
заключается в том, что это небезопасно, если $ 1
случайно содержит команду:
set -- 'ls /;true'
eval $1=new # Oops
Было бы лучше использовать printf -v
:
printf -v "$1" %s new
Но printf -v
не может назначать массивы.
Более того, eval
и printf
не будут работать, если переменная будет объявлена local
:
g() { local b; eval $1=bar; } # WRONG
g b # Conflicts with `local b'
echo $b # b is empty unexpected
Конфликт останется, даже если локальный b
не установлен
:
g() { local b; unset b; eval $1=bar; } # WRONG
g b # Still conflicts with `local b'
echo $b # b is empty unexpected