Как я могу оценить переменные окружения в Perl? - PullRequest
0 голосов
/ 19 марта 2009

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

$x=eval($ENV{EDITOR});
print $x;

выходы:

/bin/vi

отлично работает.

Если я установлю переменную окружения QUOTE на \ 'и попробую то же самое:

$x=eval($ENV{QUOTE});
print $x;

выходы:

(ничего)

$@ set to: "Can't find a string terminator anywhere before ..."

Я не хочу просто устанавливать $x=$ENV{QUOTE};, поскольку eval также используется для вызова скрипта и возврата его последнего значения (очень удобно), поэтому я бы хотел придерживаться eval (); Обратите внимание, что все переменные окружения, оцененные таким образом, установлены мной в другом месте, поэтому я не обеспокоен злонамеренным доступом к переменным окружения, оцененным таким образом.

Предложения

Ответы [ 6 ]

13 голосов
/ 19 марта 2009

Ну, конечно, это ничего не делает.

Если ваш ENV varaible содержит текст, который является наполовину кодом, но его нет, и вы передаете результирующую строку чему-то, что eval использует этот код как Perl, course собираюсь на работу.

У вас есть только 3 варианта:

  1. Программно обрабатывать строку, чтобы в ней не было неверного синтаксиса
  2. Вручную убедитесь, что ваши переменные ENV не являются мусором
  3. Найдите решение, не включающее eval , но дающее правильный результат.

Вы также можете жаловаться, что

 $x = ' 

Недопустимый код, потому что это, по сути, то, что происходит.

Образцы исправления значения 'QUOTE' для работы

# Bad. 
QUOTE="'" perl -wWe 'print eval $ENV{QUOTE}; print "$@"'
#  Can't find string terminator "'" anywhere before EOF at (eval 1) line 1.

# Bad. 
QUOTE="\'" perl -wWe 'print eval $ENV{QUOTE}; print "$@"'
#  Can't find string terminator "'" anywhere before EOF at (eval 1) line 1.

# Bad. 
QUOTE="\\'" perl -wWe 'print eval $ENV{QUOTE}; print "$@"'
#  Can't find string terminator "'" anywhere before EOF at (eval 1) line 1.

# Good
QUOTE="'\''" perl -wWe 'print eval $ENV{QUOTE}; print "$@"' 
# '
10 голосов
/ 19 марта 2009

Почему вы eval в первую очередь? Должны ли вы просто сказать

my $x = $ENV{QUOTE};
print "$x\n";

eval выполняет строку в $ENV{QUOTE}, как если бы это был код Perl, что я, безусловно, надеюсь, что это не так. Вот почему \ исчезает. Если бы вы проверили переменную $@, вы бы нашли сообщение об ошибке вроде

синтаксическая ошибка в (eval 1) строке 2, в EOF

Если переменные окружения будут содержать код, который должен выполнять Perl, вам следует заглянуть в модуль Safe . Это позволяет вам контролировать, какой код может выполняться в eval, чтобы вы случайно не выполнили что-то вроде "use File::Find; find sub{unlink $File::Find::file}, '.'"

6 голосов
/ 19 марта 2009

Оценка значения среды очень опасна и может привести к ошибкам при работе в режиме taint.

# purposely broken
QUOTE='`rm system`'

$x=eval($ENV{QUOTE});
print $x;

Теперь просто представьте, был ли этот скрипт запущен с правами root и был изменен для фактического удаления файловой системы.

2 голосов
/ 22 марта 2009

Ответ Кента, хотя и технически верен, не соответствует сути. Решение не в том, чтобы использовать eval лучше, а в том, чтобы вообще не использовать eval!

Суть этой проблемы, кажется, заключается в понимании того, что делает eval STRING (есть eval BLOCK, который совершенно отличается, несмотря на то, что имеет одно и то же имя). Он принимает строку и запускает ее как код Perl . На 99,99% это не нужно и опасно, что приводит к появлению спагетти-кода, и вам абсолютно не следует использовать его на ранних этапах вашей карьеры программиста на Perl. Вы нашли пистолет в ящике с носками вашего отца. Обнаружив, что он может продуть дыры в вещах, которые вы сейчас пытаетесь использовать, чтобы повесить плакат. Лучше забыть о его существовании, ваш код будет намного лучше.

$x = eval($ENV{EDITOR}); не делает то, что вы думаете, что делает. Мне даже не нужно знать, что вы думаете, что он делает, что вы даже использовали его там, значит, вы не знаете. Я также знаю, что вы бежите с предупреждениями, потому что Perl кричал бы на вас за это. Зачем? Предположим, что EDITOR установлено на /bin/vi. Вышеуказанное эквивалентно $x = /bin/vi, который даже не является допустимым кодом Perl.

$ EDITOR=/bin/vi perl -we '$x=eval($ENV{EDITOR}); print $x'
Bareword found where operator expected at (eval 1) line 1, near "/bin/vi"
    (Missing operator before vi?)
Unquoted string "vi" may clash with future reserved word at (eval 1) line 2.
Use of uninitialized value $x in print at -e line 1.

Я не уверен, как ты заставил это работать в первую очередь. Я подозреваю, что вы что-то упустили из своего примера. Может быть, настроить редактор, пока он не заработал?

Вам не нужно ничего делать магическим, чтобы прочитать переменную окружения. Просто $x = $ENV{EDITOR}. Готово. $x теперь /bin/vi, как вы хотели. Это так же, как $x = $y. То же самое с цитатой.

$ QUOTE=\' perl -wle '$x=$ENV{QUOTE}; print $x'
'

Готово.

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

1 голос
/ 19 марта 2009

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

$x = `$ENV{QUOTE}`
1 голос
/ 19 марта 2009

Ну, вы могли бы удвоить значение QUOTE, я полагаю, поскольку вы знаете , что оно будет eval ed.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...