Передающие аргументы ссылкой

Причина в том, что вы использовали метод readlines (), который возвращает список строк в файле. Таким образом, в вашем списке текста может быть какой-то метод, который добавляет {и} к каждому элементу списка

39
задан melpomene 8 May 2019 в 12:26
поделиться

4 ответа

Я нашел способ сделать это, но я не уверен, насколько корректный это:

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

, Таким образом, мы передаем имя переменной в противоположность значению и затем используем оценку

13
ответ дан jwfearn 27 November 2019 в 02:19
поделиться

Bash не имеет ничего как ссылки встроенным в него, таким образом, в основном единственный способ, которым Вы смогли бы сделать то, что Вы хотите, состоит в том, чтобы передать функцию название глобальной переменной, которую Вы хотите, чтобы это изменило. И даже затем Вам будет нужно eval оператор:

boo() {
    eval ${1}="new"
}

SOME_VAR="old"
echo $SOME_VAR # old
boo "SOME_VAR"
echo $SOME_VAR # new

я не думаю, что можно использовать косвенные ссылки здесь, потому что Bash автоматически получает доступ к значению переменной, имя которой хранится в косвенной ссылке. Это не дает Вам шанс установить его.

11
ответ дан David Z 27 November 2019 в 02:19
поделиться

Оценка никогда не должна использоваться на строке, которую пользователь может установить потому что его опасное. Что-то как "строка; комната-rf ~" будет плоха. Так обычно его лучшее для нахождения решений, где Вы не должны волноваться об этом.

Однако оценка будет необходима для установки переданных переменных как отмеченный комментарий.

$ y=four
$ four=4
$ echo ${!y}
4
$ foo() { x=$1; echo ${!x}; }
$ foo four
4
2
ответ дан Ian Kelling 27 November 2019 в 02:19
поделиться

Используйте вспомогательную функцию 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
16
ответ дан 27 November 2019 в 02:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: