Как увидеть синтаксические ошибки, сообщаемые с фактическими номерами строк в родительском сценарии, когда 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/(#.*)$/$comment\1$endcomment/"
Execution of -e aborted due to compilation errors.
… Но я хочу вместо этого увидеть это (фактический номер строки в родительском скрипте):
syntax error at -e line 185, near "s/(#.*)$/$comment\1$endcomment/"
То, что я пробовал (не сработало):
- присвоение
__LINE__
- даже не знаю, почему я подумал, что это сработает; это не переменная, это константа, и вы получите сообщение об ошибке
- присвоение
$.
($INPUT_LINE_NUMBER
с участиемuse English
)- Я был почти уверен, что это все равно не сработает, потому что это похоже на
NR
в Awk, и явно не для этого
- Я был почти уверен, что это все равно не сработает, потому что это похоже на
2 ответа
Как описано в 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"
Этот полезный лакомый кусочек есть в
perlrun
справочную страницу в разделе для
-x
, который "сообщает Perl, что программа встроена в более крупный фрагмент несвязанного текста, например, в почтовое сообщение".
Все ссылки программы на номера строк (предупреждения, ошибки, ...) будут относиться к
#!
line как первая строка. Таким образом, предупреждение во 2-й строке программы, которая находится на 100-й строке файла, будет отображаться как строка 2, а не как строка 100. Это можно изменить с помощью#line
директива.( См. Простые старые комментарии (нет!) Вperlsyn
)
На основе заявления, выделенного жирным шрифтом, добавление
#line NNN
(где
NNN
- это фактический номер строки родительского скрипта, в которой появляется эта директива), достигается желаемый эффект:
perl='#line 120
$inverse = "\e[7m";
$invoff = "\e[27m";
$bold = "\e[1m";
⋮
'
⋮