当 Perl 嵌入到 shell 脚本中时,如何查看父脚本中用实际行号报告的语法错误?
How to see syntax errors reported with actual line numbers in the parent script when Perl is embedded within shell script?
完全没有正当理由,我在 Bash 函数中嵌入了一个非常重要的 Perl 脚本,该函数在 autoenv .env
文件中被调用。
看起来像这样:
perl='
$inverse = "\e[7m";
$invoff = "\e[27m";
$bold = "\e[1m";
⋮
'
perl -e "$perl" "$inputfile"
我知道独立的 Perl 脚本和 PATH
变量是一回事,我知道 Term::ANSIColor 是一回事。这不是那个。
我的问题是,如果嵌入式 Perl 代码中存在语法错误,我如何让 Perl 报告 actual 行父 shell 脚本中的编号?
例如,假设 perl=
赋值发生在该文件的第 120 行,但实际 Perl 代码的第 65 行存在语法错误。我明白了:
syntax error at -e line 65, near "s/(#.*)$/$comment$endcomment/"
Execution of -e aborted due to compilation errors.
…但我想看到这个(父脚本中的实际行号):
syntax error at -e line 185, near "s/(#.*)$/$comment$endcomment/"
我尝试过的方法(没有用):
- 分配给
__LINE__
- 甚至不知道为什么我认为那会起作用;它不是一个变量,它是一个常量,你会得到一个错误说明相同
- 分配给
$.
($INPUT_LINE_NUMBER
和 use English
)
- 我很确定这无论如何都行不通,因为这就像 Awk 中的
NR
,而这显然不是它的目的
perlrun
手册页中有这个有用的花絮,在 section for -x
下,它“告诉 Perl 该程序嵌入到更大的不相关文本块中,例如在邮件中消息。
All references to line numbers by the program (warnings, errors, ...) will treat the #!
line as the first line. Thus a warning on the 2nd line of the program, which is on the 100th line in the file will be reported as line 2, not as line 100. This can be overridden by using the #line
directive. (See Plain Old Comments (Not!) in perlsyn
)
基于粗体语句,添加 #line NNN
(其中 NNN
是该指令出现的父脚本的实际行号)达到预期效果:
perl='#line 120
$inverse = "\e[7m";
$invoff = "\e[27m";
$bold = "\e[1m";
⋮
'
⋮
如perlsyn中所述,您可以使用以下指令设置行号和(可选)后续行的文件名:
#line 42 "file.pl"
这意味着您可以使用
#!/bin/sh
perl="#line 4 \"[=11=]\""'
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 }' -- "[=13=]" )
perl="#line $script_start \"[=13=]\""'
warn("test");
'
perl -e "$perl"
另一方面,bash
提供当前行号。
#!/bin/bash
script_start=$(( LINENO + 2 ))
perl="#line $script_start \"[=14=]\""'
warn("test");
'
perl -e "$perl"
完全没有正当理由,我在 Bash 函数中嵌入了一个非常重要的 Perl 脚本,该函数在 autoenv .env
文件中被调用。
看起来像这样:
perl='
$inverse = "\e[7m";
$invoff = "\e[27m";
$bold = "\e[1m";
⋮
'
perl -e "$perl" "$inputfile"
我知道独立的 Perl 脚本和 PATH
变量是一回事,我知道 Term::ANSIColor 是一回事。这不是那个。
我的问题是,如果嵌入式 Perl 代码中存在语法错误,我如何让 Perl 报告 actual 行父 shell 脚本中的编号?
例如,假设 perl=
赋值发生在该文件的第 120 行,但实际 Perl 代码的第 65 行存在语法错误。我明白了:
syntax error at -e line 65, near "s/(#.*)$/$comment$endcomment/"
Execution of -e aborted due to compilation errors.
…但我想看到这个(父脚本中的实际行号):
syntax error at -e line 185, near "s/(#.*)$/$comment$endcomment/"
我尝试过的方法(没有用):
- 分配给
__LINE__
- 甚至不知道为什么我认为那会起作用;它不是一个变量,它是一个常量,你会得到一个错误说明相同
- 分配给
$.
($INPUT_LINE_NUMBER
和use English
)- 我很确定这无论如何都行不通,因为这就像 Awk 中的
NR
,而这显然不是它的目的
- 我很确定这无论如何都行不通,因为这就像 Awk 中的
perlrun
手册页中有这个有用的花絮,在 section for -x
下,它“告诉 Perl 该程序嵌入到更大的不相关文本块中,例如在邮件中消息。
All references to line numbers by the program (warnings, errors, ...) will treat the
#!
line as the first line. Thus a warning on the 2nd line of the program, which is on the 100th line in the file will be reported as line 2, not as line 100. This can be overridden by using the#line
directive. (See Plain Old Comments (Not!) inperlsyn
)
基于粗体语句,添加 #line NNN
(其中 NNN
是该指令出现的父脚本的实际行号)达到预期效果:
perl='#line 120
$inverse = "\e[7m";
$invoff = "\e[27m";
$bold = "\e[1m";
⋮
'
⋮
如perlsyn中所述,您可以使用以下指令设置行号和(可选)后续行的文件名:
#line 42 "file.pl"
这意味着您可以使用
#!/bin/sh
perl="#line 4 \"[=11=]\""'
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 }' -- "[=13=]" )
perl="#line $script_start \"[=13=]\""'
warn("test");
'
perl -e "$perl"
另一方面,bash
提供当前行号。
#!/bin/bash
script_start=$(( LINENO + 2 ))
perl="#line $script_start \"[=14=]\""'
warn("test");
'
perl -e "$perl"