当 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/"

我尝试过的方法(没有用):

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"