2

Это действительно конкретный вопрос. У меня есть сценарий, который, судя по всему, мог бы сделать это более сложным, чем необходимо, во имя эффективности. Это действительно эффективно? Я не знаю. Это правильный способ написания? Я не знаю.

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

Этот код пытается определить переменные s$counter= s1, s2, s3, s4... в терминах ранее определенных переменных s1$j и s2$j где j - строка, являющаяся элементом списка (все определены ранее).

counter=1 
for j in ${list[@]}
    do
            eval s$counter=$(eval "echo \$s1$j")
            eval s$((counter+1))=$(eval "echo \$s2$j")
            counter=$((counter+2))
    done

Это сбивает с толку, но со мной. Внутренний eval , означающий $(eval "echo \$s1$j") должен возвращать значение s1$j . Второй eval , то есть eval s$counter =... предназначен для определения переменных s1, s2, s3, s4 ...

Так что пример будет: скажем, для первого цикла jor j=a затем $(eval "echo \$s1$j") == $s1a , со значением s1a определенным ранее в скрипте, например, пусть оно будет « s1a=10 », так что когда вычисляется второе значение eval у нас есть команда, которая заявляет « s1=10 ».

Это работает, но может ли что-то случиться, что сделает это возможной угрозой памяти или что-то в этом роде?

Та же идея с этой строкой кода.

eval $(echo "sed -i '$(eval echo '17i$sed17line')' $file")

где sed17line - это то, что я хочу добавить в строку 17 file . Это зависит от того, для чего я хочу использовать скрипт, поэтому я использую его как переменную и, следовательно, почему я использую комбинацию echo и eval .

Опять же, я просто попробовал все, что мог придумать, чтобы это имело смысл, пока результат не достиг того, чего я хотел.

Я просто хочу убедиться, что все правильно, и если есть способ улучшить это, где я должен искать эту информацию. Спасибо!

1 ответ1

1

Хорошо знать, что есть проблемы с eval (этим и этим) и echo (здесь). Вы должны избегать eval , его легко использовать неправильно.

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


Ваш первый пример становится намного чище с массивами. Это работает в GNU bash 4.4.12 в моем Debian:

# preparing variables
unset -v list s s1 s2
declare -a list=( foo 'X Y' bar baz )
declare -a s
declare -A s1=( [foo]='FOO 1' [bar]='BAR 2' [baz]='BAZ beep; eject /dev/sr0' )
declare -A s2=( [foo]='oof oof' [bar]='rab rab' [baz]='zab zab' [X Y]='9')

# your code rewritten, we don't even need a counter
for j in "${list[@]}"
  do
    s+=( "${s1[$j]}" "${s2[$j]}" )
  done

# checking contents of s
printf '%s\n' "${s[@]}"

Подсказка: исследуйте "индексированные массивы", "ассоциативные массивы" и их использование в bash .

Обратите внимание, что элемент с пробелом (X Y) не является для меня чем-то особенным; но это сломало бы ваш код. У меня также может быть BAZ beep; eject /dev/sr0 в моем s1 ; Смею вас установить s1baz='BAZ beep; eject /dev/sr0' , добавьте baz в list , выполните ваш код и посмотрите, что произойдет. Это то, на что способен eval . Теперь представьте, что я поставил rm -rf ~/ вместо eject …


Второй пример может быть значительно упрощен как:

sed -i "17i$sed17line" "$file"

Похоже, у вас есть склонность к eval + echo так как вы создали хитрое устройство, которое использует их дважды, когда ничего не нужно. Возможно, это потому, что ваши переменные не всегда расширяются до значений, когда вы этого хотите; если это так, исследуйте разницу между одинарными (') и двойными кавычками (") в bash .

Слава за то, что сомневался и задавал вопрос.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .