#bash #perl #syntax-error #runtime-error #embedded-script
#bash #perl #синтаксическая ошибка #ошибка во время выполнения #встроенный скрипт
Вопрос:
Без какой-либо уважительной причины у меня есть довольно существенный скрипт Perl, встроенный в функцию Bash, которая вызывается в файле autoenv .env
.
Это выглядит примерно так:
perl='
$inverse = "e[7m";
$invoff = "e[27m";
$bold = "e[1m";
⋮
'
perl -e "$perl" "$inputfile"
Я понимаю, что автономные скрипты Perl и PATH
переменная — это нечто, и я понимаю, что Term::ANSIColor — это нечто. Речь не об этом.
Мой вопрос в том, что если во встроенном коде Perl есть синтаксическая ошибка, как я могу заставить Perl сообщать фактический номер строки в родительском сценарии оболочки?
Например, скажем, perl=
присвоение происходит в строке 120 в этом файле, но в 65-й строке фактического кода Perl есть синтаксическая ошибка. Я понимаю это:
syntax error at -e line 65, near "s/(#.*)$/$comment1$endcomment/"
Execution of -e aborted due to compilation errors.
… но я хочу видеть это (фактический номер строки в родительском скрипте) вместо этого:
syntax error at -e line 185, near "s/(#.*)$/$comment1$endcomment/"
То, что я пробовал (это не сработало):
- присвоение
__LINE__
- даже не знаю, почему я думал, что это сработает; это не переменная, это константа, и вы получаете сообщение об ошибке, указывающее то же самое
- присвоение
$.
($INPUT_LINE_NUMBER
сuse English
помощью)- Я был почти уверен, что это все равно не сработает, потому что это похоже на
NR
в Awk, и это явно не то, для чего это нужно
- Я был почти уверен, что это все равно не сработает, потому что это похоже на
Ответ №1:
Как описано в perlsyn, вы можете использовать следующую директиву, чтобы задать номер строки и (необязательно) имя файла последующей строки:
#line 42 "file.pl"
Это означает, что вы могли бы использовать
#!/bin/sh
perl="#line 4 "$0""'
warn("test");
'
perl -e "$perl"
Вывод:
$ ./a.sh
test at ./a.sh line 4.
Нет чистого способа избежать жесткого кодирования номера строки при использовании sh
, но это возможно.
#!/bin/sh
script_start=$( perl -ne'if (/^perl=/) { print $. 1; last }' -- "$0" )
perl="#line $script_start "$0""'
warn("test");
'
perl -e "$perl"
С другой стороны, bash
предоставляет текущий номер строки.
#!/bin/bash
script_start=$(( LINENO 2 ))
perl="#line $script_start "$0""'
warn("test");
'
perl -e "$perl"
Ответ №2:
На perlrun
странице руководства, в разделе для -x
, есть этот полезный момент, который «сообщает Perl, что программа встроена в больший фрагмент несвязанного текста, например, в почтовом сообщении».
Все ссылки на номера строк программой (предупреждения, ошибки, …) будут рассматривать
#!
строку как первую строку. Таким образом, предупреждение во 2-й строке программы, которая находится на 100-й строке в файле, будет отображаться как строка 2, а не как строка 100. Это можно переопределить с помощью#line
директивы. (Смотрите Простые старые комментарии (нет!) вperlsyn
)
На основе выделенного жирным шрифтом утверждения добавление #line NNN
(где NNN
— фактический номер строки родительского скрипта, в котором появляется эта директива) достигает желаемого эффекта:
perl='#line 120
$inverse = "e[7m";
$invoff = "e[27m";
$bold = "e[1m";
⋮
'
⋮
Комментарии:
1. Это выводится
-e
как имя файла. Вы можете передать второй аргумент для#line
указания имени файла. Заключите его в двойные кавычки.2. @ikegami Для начала это был такой запутанный скрипт, что я был полностью согласен с
-e
, но это отличный совет!