Временное значение bash скрипта по команде

Да, я нашел решение, использующее сочетание массивов и sed ..:

#delete the old values
sed -i 's/speed:\(.\), //g' "$FILENAME"
sed -i 's/speed:\(..\), //g' "$FILENAME"
sed -i 's/speed:\(...\), //g' "$FILENAME"
sed -i 's/speed:\(....\), //g' "$FILENAME"

#create an array with just the urls
SERVER=( $(sed -nre 's/.*server:"(.*)".*/\1/p' "$FILENAME") )

#for each element
for element in $(seq 0 $((${#SERVER[@]}-1)))
do
    #calculate the new average ping speed
    SPEED[element]="$( sudo ping -c2 "${SERVER[element]}" | grep rtt | cut -f 5 -d '/' )"

    #if server is not available
    if [ -z "${SPEED[element]}" ]; then SPEED[element]=1000 ; fi

    #add the old server speed
    sed -i "s/\"\(${SERVER[element]}\)\"/\"\1\", speed:${SPEED[element]}/g" "$FILENAME"
done

Может быть, не работает, но работает и может быть полезно

11
28.02.2016, 17:13
3 ответа

Это сводится к вопросу о том, как работает оценка. Оба примера работают одинаково, проблема возникает из-за того, как оболочка (здесь bash) расширяет переменные.

Когда вы пишете эту команду:

HOME="foo" echo $HOME

$ HOME раскрывается перед запуском команды . Следовательно, оно расширяется до исходного значения, а не до нового значения, которое вы установили для команды. Переменная HOME действительно была изменена в среде, в которой выполняется команда echo , однако вы печатаете $ HOME из родительского объекта.

Для иллюстрации рассмотрим следующее:

$ HOME="foo" bash -c 'echo $HOME'
foo
$ echo $HOME
/home/terdon

Как вы можете видеть выше, первая команда печатает временно измененное значение HOME , а вторая печатает оригинал, демонстрируя, что переменная была изменена только временно. Поскольку bash -c ... команда заключена в одинарные кавычки ( '' ) вместо двойных ( «» ), переменная не раскрывается и передается как есть в новый процесс bash. . Затем этот новый процесс расширяет его и печатает новое значение, на которое он был установлен. В этом можно убедиться, если использовать set -x :

$ set -x
$ HOME="hello" echo "$HOME"
+ HOME=hello         
+ echo hello
hello

Как видно выше, переменная $ HOME никогда не передается в echo ]. Он видит только его расширенную ценность. Сравните с:

$ HOME="hello" bash -c 'echo $HOME'
+ HOME=hello
+ bash -c 'echo $HOME'
hello

Здесь из-за одинарных кавычек переменная, а не ее значение, передаются новому процессу.

9
27.01.2020, 19:59

Существует две области действия: переменные среды и локальные переменные. Переменные среды действительны для каждого процесса (см. setenv , getenv ), а локальные переменные - активен только в рамках этого сеанса оболочки. (Это не очевидное различие ...)

Подразумеваемое env (как в вашем примере) изменяет среду, а echo ... использует локальные, поэтому ] env не действует.

Чтобы изменить локальные переменные, используйте, скажем,

( HOME="foo" ; echo "$HOME" )

Здесь круглые скобки определяют объем этого присваивания.

-1
27.01.2020, 19:59

Когда оболочка анализирует строку, она разбивает строку на слова, выполняет различные расширения (по порядку) для слов , затем выполните команду.

Предположим, test = 1: 2: 3: 4: 5: 6

Давайте посмотрим на эту команду: IFS = ":" read abcdef <<< "$ test"

После происходит разметка и расширение параметра : IFS = ":" читать a b c d e f <<< "1: 2: 3: 4: 5: 6"

Оболочка установит переменную IFS на время выполнения команды чтения, а read знает, как примените $ IFS к его входу и присвойте значения именам переменных.

Эта команда имеет аналогичную историю, но другой результат: HOME = "hello" echo "$ HOME"

Поскольку расширение параметра происходит до начала команды, оболочка имеет:

HOME="hello" echo "/home/username"

И затем, во время выполнения команды echo, новое значение $ HOME вообще не используется.

Чтобы достичь того, что вы пытаетесь сделать, выберите одно из

# Delay expansion of the variable until its new value is set
HOME="hello" eval 'echo "$HOME"'

или

# Using a subshell, so the altered env variable does not affect the parent.
# The semicolon means that the variable assignment will occur before
# the variable expansion
(HOME="hello"; echo "$HOME")

, но не выбирайте первый.

9
27.01.2020, 19:59

Теги

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