perl脚本中使用eval函数执行可能有异常的操作

Perl中的eval块:深入解析与应用 块是Perl编程中一个强大而有用的工具,它允许开发者捕获和处理代码执行过程中的错误,并提供了执行动态代码的能力。块是一个非常重要的特性,它允许开发者捕获和处理异常,同时也提供了一种执行动态代码的方法。块可以执行动态代码,但它也可能带来安全风险,特别是当执行的代码来源于不可信的用户输入时。块中的代码,如果在执行过程中遇到错误,Perl不会立即抛出异常,而是将错误信息存储在特殊的变量。块在Perl中用于捕获代码执行过程中的错误。块的作用、用法以及在Perl编程中的应用场景。变量中的字符串作为Perl代码。 阅读详情

perl脚本中有时候执行的操作可能会引发异常,为了直观的说明,这里举一个json反序列化的例子,脚本如下:

#! /usr/bin/perl
use v5.14;
use JSON;
use Data::Dumper;

# 读取json字符串数据
my $json_str = join('', <DATA>);
# 反序列化操作
my $json = from_json($json_str);

say to_json($json, { pretty => 1 });

__DATA__
bad {
   "id" : 1024,
   "desc" : "hello world",
   "other" : {
      "test_null" : null,
      "test_false" : false,
      "test_true" : true
   }
}


在这里插入图片描述

脚本中有意把正确json字符串之前加了几个字符,显然这个json字符串是不符合规范格式的,在git bash中执行这个脚本,结果如下:
在这里插入图片描述

下面用perl的eval函数改造这个脚本:

#! /usr/bin/perl
use v5.14;
use JSON;
use Data::Dumper;

# 读取json字符串数据
my $json_str = join('', <DATA>);
# 反序列化操作
my $json = eval {
	return from_json($json_str);
};

unless (defined $json) {
	say "from_json failed !!!!";
} else {
	say to_json($json, { pretty => 1 });
}

__DATA__
bad {
   "id" : 1024,
   "desc" : "hello world",
   "other" : {
      "test_null" : null,
      "test_false" : false,
      "test_true" : true
   }
}


脚本中用把from_json的操作放在eval函数中,输出结果如下:
在这里插入图片描述
显然,这个结果是可控的,可预期的。比如就可以使用这种方法判断json字符串是否合法,能够正常反序列化的就是合法的,否则就是非法的。eval函数的具体使用可以使用perldoc -f eval查看。

    eval EXPR
    eval BLOCK
    eval    "eval" in all its forms is used to execute a little Perl
            program, trapping any errors encountered so they don't crash the
            calling program.

            Plain "eval" with no argument is just "eval EXPR", where the
            expression is understood to be contained in $_. Thus there are
            only two real "eval" forms; the one with an EXPR is often called
            "string eval". In a string eval, the value of the expression
            (which is itself determined within scalar context) is first
            parsed, and if there were no errors, executed as a block within
            the lexical context of the current Perl program. This form is
            typically used to delay parsing and subsequent execution of the
            text of EXPR until run time. Note that the value is parsed every
            time the "eval" executes.

            The other form is called "block eval". It is less general than
            string eval, but the code within the BLOCK is parsed only once
            (at the same time the code surrounding the "eval" itself was
            parsed) and executed within the context of the current Perl
            program. This form is typically used to trap exceptions more
            efficiently than the first, while also providing the benefit of
            checking the code within BLOCK at compile time. BLOCK is parsed
            and compiled just once. Since errors are trapped, it often is
            used to check if a given feature is available.

            In both forms, the value returned is the value of the last
            expression evaluated inside the mini-program; a return statement
            may also be used, just as with subroutines. The expression
            providing the return value is evaluated in void, scalar, or list
            context, depending on the context of the "eval" itself. See
            "wantarray" for more on how the evaluation context can be
            determined.

            If there is a syntax error or runtime error, or a "die"
            statement is executed, "eval" returns "undef" in scalar context,
            or an empty list in list context, and $@ is set to the error
            message. (Prior to 5.16, a bug caused "undef" to be returned in
            list context for syntax errors, but not for runtime errors.) If
            there was no error, $@ is set to the empty string. A control
            flow operator like "last" or "goto" can bypass the setting of
            $@. Beware that using "eval" neither silences Perl from printing
            warnings to STDERR, nor does it stuff the text of warning
            messages into $@. To do either of those, you have to use the
            $SIG{__WARN__} facility, or turn off warnings inside the BLOCK
            or EXPR using "no warnings 'all'". See "warn", perlvar, and
            warnings.

            Note that, because "eval" traps otherwise-fatal errors, it is
            useful for determining whether a particular feature (such as
            "socket" or "symlink") is implemented. It is also Perl's
            exception-trapping mechanism, where the "die" operator is used
            to raise exceptions.

            Before Perl 5.14, the assignment to $@ occurred before
            restoration of localized variables, which means that for your
            code to run on older versions, a temporary is required if you
            want to mask some, but not all errors:

             # alter $@ on nefarious repugnancy only
             {
                my $e;
                {
                  local $@; # protect existing $@
                  eval { test_repugnancy() };
                  # $@ =~ /nefarious/ and die $@; # Perl 5.14 and higher only
                  $@ =~ /nefarious/ and $e = $@;
                }
                die $e if defined $e
             }

            There are some different considerations for each form:

            String eval
                Since the return value of EXPR is executed as a block within
                the lexical context of the current Perl program, any outer
                lexical variables are visible to it, and any package
                variable settings or subroutine and format definitions
                remain afterwards.

                Under the "unicode_eval" feature
                    If this feature is enabled (which is the default under a
                    "use 5.16" or higher declaration), EXPR is considered to
                    be in the same encoding as the surrounding program. Thus
                    if "use utf8" is in effect, the string will be treated
                    as being UTF-8 encoded. Otherwise, the string is
                    considered to be a sequence of independent bytes. Bytes
                    that correspond to ASCII-range code points will have
                    their normal meanings for operators in the string. The
                    treatment of the other bytes depends on if the
                    "'unicode_strings"" feature is in effect.

                    In a plain "eval" without an EXPR argument, being in
                    "use utf8" or not is irrelevant; the UTF-8ness of $_
                    itself determines the behavior.

                    Any "use utf8" or "no utf8" declarations within the
                    string have no effect, and source filters are forbidden.
                    ("unicode_strings", however, can appear within the
                    string.) See also the "evalbytes" operator, which works
                    properly with source filters.

                    Variables defined outside the "eval" and used inside it
                    retain their original UTF-8ness. Everything inside the
                    string follows the normal rules for a Perl program with
                    the given state of "use utf8".

                Outside the "unicode_eval" feature
                    In this case, the behavior is problematic and is not so
                    easily described. Here are two bugs that cannot easily
                    be fixed without breaking existing programs:

                    *   It can lose track of whether something should be
                        encoded as UTF-8 or not.

                    *   Source filters activated within "eval" leak out into
                        whichever file scope is currently being compiled. To
                        give an example with the CPAN module
                        Semi::Semicolons:

                         BEGIN { eval "use Semi::Semicolons; # not filtered" }
                         # filtered here!

                        "evalbytes" fixes that to work the way one would
                        expect:

                         use feature "evalbytes";
                         BEGIN { evalbytes "use Semi::Semicolons; # filtered" }
                         # not filtered

                Problems can arise if the string expands a scalar containing
                a floating point number. That scalar can expand to letters,
                such as "NaN" or "Infinity"; or, within the scope of a "use
                locale", the decimal point character may be something other
                than a dot (such as a comma). None of these are likely to
                parse as you are likely expecting.

                You should be especially careful to remember what's being
                looked at when:

                    eval $x;        # CASE 1
                    eval "$x";      # CASE 2

                    eval '$x';      # CASE 3
                    eval { $x };    # CASE 4

                    eval "\$$x++";  # CASE 5
                    $$x++;          # CASE 6

                Cases 1 and 2 above behave identically: they run the code
                contained in the variable $x. (Although case 2 has
                misleading double quotes making the reader wonder what else
                might be happening (nothing is).) Cases 3 and 4 likewise
                behave in the same way: they run the code '$x', which does
                nothing but return the value of $x. (Case 4 is preferred for
                purely visual reasons, but it also has the advantage of
                compiling at compile-time instead of at run-time.) Case 5 is
                a place where normally you *would* like to use double
                quotes, except that in this particular situation, you can
                just use symbolic references instead, as in case 6.

                An "eval ''" executed within a subroutine defined in the
                "DB" package doesn't see the usual surrounding lexical
                scope, but rather the scope of the first non-DB piece of
                code that called it. You don't normally need to worry about
                this unless you are writing a Perl debugger.

                The final semicolon, if any, may be omitted from the value
                of EXPR.

            Block eval
                If the code to be executed doesn't vary, you may use the
                eval-BLOCK form to trap run-time errors without incurring
                the penalty of recompiling each time. The error, if any, is
                still returned in $@. Examples:

                    # make divide-by-zero nonfatal
                    eval { $answer = $a / $b; }; warn $@ if $@;

                    # same thing, but less efficient
                    eval '$answer = $a / $b'; warn $@ if $@;

                    # a compile-time error
                    eval { $answer = }; # WRONG

                    # a run-time error
                    eval '$answer =';   # sets $@

                If you want to trap errors when loading an XS module, some
                problems with the binary interface (such as Perl version
                skew) may be fatal even with "eval" unless
                $ENV{PERL_DL_NONLAZY} is set. See perlrun.

                Using the "eval {}" form as an exception trap in libraries
                does have some issues. Due to the current arguably broken
                state of "__DIE__" hooks, you may wish not to trigger any
                "__DIE__" hooks that user code may have installed. You can
                use the "local $SIG{__DIE__}" construct for this purpose, as
                this example shows:

                    # a private exception trap for divide-by-zero
                    eval { local $SIG{'__DIE__'}; $answer = $a / $b; };
                    warn $@ if $@;

                This is especially significant, given that "__DIE__" hooks
                can call "die" again, which has the effect of changing their
                error messages:

                    # __DIE__ hooks may modify error messages
                    {
                       local $SIG{'__DIE__'} =
                              sub { (my $x = $_[0]) =~ s/foo/bar/g; die $x };
                       eval { die "foo lives here" };
                       print $@ if $@;                # prints "bar lives here"
                    }

                Because this promotes action at a distance, this
                counterintuitive behavior may be fixed in a future release.

                "eval BLOCK" does *not* count as a loop, so the loop control
                statements "next", "last", or "redo" cannot be used to leave
                or restart the block.

                The final semicolon, if any, may be omitted from within the
                BLOCK.


8、Perl中eval的使用详解 本文详细解析了Perl中`eval`的多种使用场景和技巧,包括块形式的异常处理、结合`die`实现自定义错误抛出、使用`eval`进行表达式求值、替换中的表达式求值、提高代码效率的动态代码生成、以及结合`alarm`实现超时控制。同时,文章也讨论了`eval`使用中的注意事项,如安全风险、性能问题和错误处理。最后,通过对比总结,帮助开发者更好地理解`eval`在不同场景下的应用和优化方法。 阅读详情

相关推荐

9、Perl编程:Eval、模块与异常处理全解析

本文深入解析了Perl编程中的Eval机制、模块开发基础与异常处理策略。重点介绍了如何利用eval和die实现程序的超时控制,探讨了Perl中模块的定义与使用方法,包括包声明、加载路径及隐私性控制,并比较了不同编程语言在运行时评估与异常处理方面的差异。适合有一定Perl基础的开发者参考学习,以提升代码的组织结构、异常容错能力以及模块化开发水平。

swift5iosmith的博客 90

perl下 eval 函数执行解说

perl下 eval 函数执行解说

oligaga的博客 887

二次开发vba_CATIA VBA(VBS)二次开发:使用Search批量选择元素

在CATIA二次开发中很多在程序中进行自动交互的方法或函数都需要使用选择集作为参数,将几何元素按照要求批量添加到选择集中也是实现程序自动运行的有效方法。在前面的文章《CATIA使用VBA(VBS)二次开发时用户的交互选择》和《CATIA使用VBA(VBS)二次开发时工程图和草图位置的交互选择函数Indicate2D》中介绍了在CATIA VBA(VBS)二次开发中用户和选择集之间的交互操...

weixin_32497403的博客 1321

perl函数说明(eval)

eval BLOCK eval EXPR eval eval 关键字在 Perl 里起两种不同的但相关的作用。这些目的是用两种形式的语法来表现的, eval BLOCK 和 eval EXPR。第一种形式捕获那些致命的运行时例外(错误),类似于 C++ 或 Java 里的 “try 块”。第二种形式在运行时实时地编译和执行一小段代码,并且也和第一种形式一样捕获任何例外。但是第二种形式比第一种形

紫轩阁 5672

2026华为OD机试(C语言)真题【E卷+A卷+B卷+C卷+D卷】目录+在线OJ

华为OD机试真题题库【E卷+A卷+B卷+C卷+D卷】目录,C语言实现。

MISAYAONE的博客 11万+

行为预测模型:Social LSTM与Graph Neural Networks

行为预测模型:Social LSTM与Graph Neural Networks ,人工智能,计算机视觉,大模型,AI,本文围绕行为预测模型Social LSTM与Graph Neural Networks展开,介绍了两者的基础概念、原理、应用场景,还对比了它们在优势、劣势和适用场景上的不同,最后给出了相应的代码示例。Social LSTM基于LSTM,通过社交池化层处理多智能体交互;图神经网络处理图结构数据,靠消息传递获取信息,二者各有侧重,适用于不同场景。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 15万+

Perl eval 函数探讨

   Perl eval 函数探讨     Perl 作为一种脚本语言可以实时地生成和执行代码。这种特性可以把代码的编译推迟到运行时,所以又称为“动态代码”。另外, Pe

EagleYIN417的专栏 1045

安卓中蓝牙免提HFP的一些分析

最近看了一些大牛的博客,无不提到了技术分享的重要性,的确,分享自己的知识不仅仅是与他人讨论并相互提高的过程,更是对自己知识的梳理。希望自己能以此为契机,形成周期性博客分享的习惯。 文章标题为HFP的一些分析,HFP(Hand Free Profile)主要定义了安卓中与接打电话相关的一些功能的实现。本文主要介绍这其中对于HFP非常重要的Service Level Connection的建立。首先...

底层码农 771

Perl eval函数探讨

转自:http://weidagang2046.blog.51cto.com/246444/45923/ Perl 作为一种脚本语言可以实时地生成和执行代码。这种特性可以把代码的编译推迟到运行时,所以又称为“动态代码”。另外, Perl 也如 Java 、 C++ 一样提供了异常处理机制。本文将初步探讨Perl 中实现动态代码和异常处理机制的函数: eval 。如有错误不足,欢迎讨论和批评指正。 

http://itech.cnblogs.com 730

YOLOv13优化Faster_Block:卷积(Partial Convolution)、多层感知机(MLP)结构和残差连接

Faster_Block 代表了现代深度学习中效率与性能平衡的一个典型案例。它通过部分卷积技术巧妙地减少了计算开销,同时通过精心设计的架构保持了强大的特征学习能力。这种设计思想对于移动端部署、实时应用和大规模模型训练都具有重要意义。 未来的发展方向可能包括更智能的动态分割策略、与新兴硬件的深度适配,以及与其他先进技术(如自注意力机制、神经架构搜索等)的结合。Faster_Block 的成功展示了在深度学习领域,创新往往来自于对问题本质的深刻理解和巧妙的工程实现。

FJN110的博客 427

39-OpenLayers多图层切换显示隐藏,支持多个Layer同时显示和隐藏,OpenLayers懒加载瓦片

39-OpenLayers多图层切换显示隐藏,支持多个Layer同时显示和隐藏,OpenLayers懒加载瓦片

fxshy的博客 462

Perl中的eval

本文和大家重点讨论一下Perl Perl eval函数的概念,Perl eval函数可以看作是Perl虚拟机,它的参数就是一段Perl代码,并且利用’Perldoc–feval’可以获取Perl eval函数使用帮助。具体内容请看本文详细介绍。 Perl eval函数探讨 Perl作为一种脚本语言可以实时地生成和执行代码。这种特性可以把代码的编译推迟到运行时,所以又称为“动态代码”。另外,P...

乐在其中/Leo在其中 694

基于高光谱的物质反演与分类 — 技术文章(原理详解 + 深度代码实现)

高光谱遥感 / 近场光谱采集产生逐像素上百波段的光谱曲线,是物质识别与定量反演(abundance / composition estimation)和语义分类(landcover / material class)的一把利器。本文第一部分对常用模型(线性混合模型、非线性辐射传输、稀疏反演、降维与特征选择、分类器/神经网络)进行数学推导与理论分析;第二部分给出两套完整实现:A. 基于 LMM 的约束最小二乘 / 稀疏反演流水线(含端到端评估);

VectorShift的博客 219

【转】Perl的die、warn、eval函数

在Windows中,不能使用 or die $!. die函数 18.4 错误处理 在很多情况下,系统调用可能会失败;例如,尝试打开不存在的文件,或者删除某个仍含有文件的目录,或者尝试读取没有读权限的文件。在前面的示例中,我们已经用到了die函数,本节将 详细讨论有关错误处理和错误处理函数的相关内容。这些函数包括die函数、warn函数和eval函数。 die函数用于在命令

Eucalyptus 841

[个人自用,全网最优]EDEM-FLUENT个人自学教程,拒绝手忙脚乱无用功!

[个人自用,全网最优]EDEM-FLUENT个人自学教程,拒绝手忙脚乱无用功!

zheaa的博客 4826

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Perl中的alarm、eval、die的联合使用

1. eval: eval是一个表达式,而不是if和while这样的控制结构,eval块发生严重错误时,eval块会停止执行,但程序不会崩溃。所以在程序中执行有可能引起严重错误的代码块,但又不想影响后续程序的执行时,可以把这部分代码块放入eval中。eva块正常执行,还是发生了严重错误,放在$@中,如果没错,$@为空,否则存放错误的原因。可以用$@的boolean值判断结果:print $@ i

勤劳的小蜜蜂 2413

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

perl中eval函数的两种使用方式

zz: http://developer.51cto.com/art/201007/211869.htm 本文和大家重点讨论一下Perl Perl eval函数的概念,Perl eval函数可以看作是Perl虚拟机,它的参数就是一段Perl代码,并且利用’Perldoc–feval’可以获取Perl eval函数使用帮助。具体内容请看本文详细介绍。 Perl eval函数探讨 P

sxlwzl的专栏 1850

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Perl 语言开发(十一):异常处理,提升 Perl 代码鲁棒性的关键

在 Perl 编程中,异常处理是确保代码健壮性和可靠性的重要环节。通过适当的异常处理,我们可以捕获并处理运行时错误,防止程序崩溃,并提供有意义的错误信息给用户或日志系统。这篇文章将深入探讨 Perl 中的异常处理技术,从基础概念到高级应用,帮助开发者写出更健壮、更可靠的 Perl 代码。

1486

perl的异常处理die、warn、eval函数--DBI的RaiseError

在很多情况下,系统调用可能会失败;例如,尝试打开不存在的文件,或者删除某个仍含有文件的目录,或者尝试读取没有读权限的文件。在前面的示例中,我们已经用到了die函数,本节将 详细讨论有关错误处理和错误处理函数的相关内容。这些函数包括die函数、warn函数和eval函数。 die函数用于在命令或文件句柄失败时退出Perl脚本。 warn函数类似于die函数,但它不会退出脚本。

直到世界的尽头 1万+

中级perl--用eval捕捉错误

有一些代码看上去很平常,但是却含有潜在的危险,一旦某种条件不对就会使程序中断,过早地结束程序。 my $average = $total / $count; # 除数为零 print "okayn" unless /$match/; # 正则表达式不合法 open MINNOW,‘>ship.txt’or die "Can‘t create ‘ship.txt’: $!"; # 文件句柄...

jinYwuM的博客 609

深入Perl的eval块:错误捕获与异常处理的艺术

最后,本文将总结eval块的关键点,并提供一些最佳实践,帮助读者更有效地使用eval块进行错误捕获和异常处理。通过深入理解eval块的工作原理和高级用法,Perl程序员可以更有效地处理程序中的错误和异常,编写出更加健壮和安全的代码。

2402_85762143的博客 1179

perl 是用 eval 实现异常处理

            $in = "20080230100000" ; # error            $mon=substr($in,4,2);              $day=substr($in,6,2);              $mon++;$mon--;              $day++;$day--;              $year =

dongdongk的专栏 3089

PERL 用EVAL 来捕捉异常Exception

$total=0;$count=0;eval { $average = $total / $count ; print "xxx/n";} ; if ($@){  print "wrong /n";}else{  print "right/n";} eval块的结束时的分号是必须的,因为不像 if或者while那样的控制结构,eval实际上是个函数。但是代码块是真的块,所以可以包括词法

中关村村长的专栏 4847

Perl eval函数使用实例

Perl eval函数使用实例 投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014-11-24 我要评论 这篇文章主要介绍了Perl eval函数使用实例,本文讲解了eval 函数的两种使用方式,并给出3个使用实例,需要的朋友可以参考下 Perl 作为一种脚本语言可以实时地生成和执行代码。这种特性可以把代码的编译推迟到运行时,所以又称为“动态代码

aids260的博客 679
上一篇: perl处理json的序列化和反序列化
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值