Ошибка bash / shell при запуске perl -e 'use [module]': не удается найти терминатор строки "'" где-либо до EOF в строке -e 1 - PullRequest
3 голосов
/ 22 марта 2012

Я пишу сценарий оболочки, который перед запуском должен проверить, что системные обновления Perl не сломали склеенные сценарии Perl. Я продолжаю получать то, что выглядит как ошибка синтаксического анализа. Чтобы воспроизвести это в командной строке:

$ module='Scalar::Util'; check="perl -e 'use $module' 2>&1"; check_status=`$check`; echo $check
Can't find string terminator "'" anywhere before EOF at -e line 1.
perl -e 'use Scalar::Util' 2>&1

Кто-нибудь видит, что я делаю не так?

Спасибо.

Ответы [ 4 ]

9 голосов
/ 22 марта 2012

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

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

У вас есть:

module='Scalar::Util'
check="perl -e 'use $module' 2>&1"
check_status=`$check`
echo $check

Проблема в том, что при обработке оболочки:

`$check`

разбивает строку на границах слова, получая аргументы:

perl
-e
'use
Scalar::Util'
2>&1

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

module='Scalar::Util'
check="perl -e 'use $module' 2>&1"
check_status=`eval $check`
echo $check

eval заставляет оболочку выполнить повторный анализ строки, не получая ошибок.

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

Один из способов проверить, существует ли модуль в Perl:1025 *

Это дает номер версии модуля (и усложняет строку).Вы также можете просто сделать:

perl -M$module -e exit

, который выйдет со статусом 0, если модуль загружен, и выдаст ошибки и т.д., если это не так.

$  perl -MSalar::Util -e exit
Can't locate Salar/Util.pm in @INC (@INC contains: /Users/jleffler/Perl/v5.14.1-64/lib/perl5/site_perl/5.14.1/darwin-2level /Users/jleffler/Perl/v5.14.1-64/lib/perl5/site_perl/5.14.1 /Users/jleffler/Perl/v5.14.1-64/lib/perl5/5.14.1/darwin-2level /Users/jleffler/Perl/v5.14.1-64/lib/perl5/5.14.1 .).
BEGIN failed--compilation aborted.
$ echo $?
2
$
1 голос
/ 22 марта 2012

Обычно, если вы помещаете команды в переменную, оболочка анализирует строку только один раз (то есть, когда она расширяет переменную) и поэтому не будет обрабатывать ее, если сама команда содержит специальные символы оболочки.В вашем случае оболочкой являются ' и 2>&1.Вот почему Bash дает вам ошибку.Даже если вы удалите ' s с помощью -m$module, вы все равно получите ошибки о 2>&1

Так что, как сказано в ответах выше, вам нужно использовать eval или вызвать вспомогательную оболочку (bash или sh) для принудительного анализа переменной.

Если все, что вы делаете, это проверяете, что perl скомпилирует требуемый модуль, этого достаточно?Здесь ok будет 0, если все круто, или не равно 0, если произошла какая-то ошибка.Может не подойти, если ваша реальная проблема намного сложнее, чем приведенный пример.

1 голос
/ 22 марта 2012

Я не уверен, что делает оболочка, но, похоже, работает $check в sh:

module='Scalar::Util'; check="perl -e 'use $module' 2>&1";echo $check |sh

Однако было бы гораздо менее неуклюже использовать для этого что-то вроде Module::Load::Conditional. Вы также можете использовать pminst.

0 голосов
/ 22 марта 2012

Единственный безопасный способ сделать это в bash - это использовать массив. Это будет правильно поддерживать аргументы с пробелами.

module='Scalar::Util' 
check=(perl -e "use $module")
check_status=$("${check[@]}" 2&>1)   # must use quotes here
status=$?
echo "$status: $check"

Обратите внимание, что перенаправление stderr / stdout не может быть частью массива команд, вы должны указать его как часть команды, иначе это просто еще один строковый параметр для команды perl.

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