解释Perl的“序言"的曲解 [英] Explain the deviousness of the Perl "preamble"

查看:114
本文介绍了解释Perl的“序言"的曲解的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Perl手册描述了一个完全曲折的构造,该构造可在csh,sh或Perl中的任何一种下工作,例如以下

The Perl manual describes a totally devious construct that will work under any of csh, sh, or Perl, such as the following:

eval '(exit $?0)' && eval 'exec perl -wS $0 ${1+"$@"}'
    & eval 'exec /usr/bin/perl -wS $0 $argv:q'
    if $running_under_some_shell;

确实不真实...有人可以详细解释它的工作原理吗?

Devious indeed... can someone please explain in detail how this works?

推荐答案

想法是,如果在标准的Bourne shell(sh),C shell(csh)或Perl.仅在不支持在脚本开头使用#!行指定解释器名称的系统上,才需要使用此技巧.如果您以这3行开头的Perl脚本作为Shell脚本执行,则Shell将启动Perl解释器,并向其传递脚本的文件名和命令行参数.

The idea is that those three lines do 3 different things if they're evaluated in a standard Bourne shell (sh), a C shell (csh), or Perl. This hack is only needed on systems that don't support specifying an interpreter name using a #! line at the start of a script. If you execute a Perl script beginning with those 3 lines as a shell script, the shell will launch the Perl interpreter, passing it the script's filename and the command line arguments.

在Perl中,三行形成一个语句,以;终止,形式为

In Perl, the three lines form one statement, terminated by the ;, of the form

eval '...' && eval '...' & eval '...' if $running_under_some_shell;

由于脚本刚刚启动,所以$running_under_some_shellundef,这是错误的,并且永远不会执行评估.这是无人操作.

Since the script just started, $running_under_some_shell is undef, which is false, and the evals are never executed. It's a no-op.

曲折的部分是$?0在sh和csh中的解析方式有所不同.在sh中,这意味着$?(最后一个命令的退出状态)后跟0.由于没有上一个命令,$?将为0,因此$?0的值为00.在csh中,$?0是一个特殊变量,如果知道当前输入的文件名,则为1,否则为0.由于外壳程序正在从脚本读取这些行,因此$?0将为1.

The devious part is that $?0 is parsed differently in sh versus csh. In sh, that means $? (the exit status of the last command) followed by 0. Since there is no previous command, $? will be 0, so $?0 evaluates to 00. In csh, $?0 is a special variable that is 1 if the current input filename is known, or 0 if it isn't. Since the shell is reading these lines from a script, $?0 will be 1.

因此,在sh中,eval '(exit $?0)'表示eval '(exit 00)',在csh中表示eval '(exit 1)'.括号表示应该在子外壳中评估exit命令.

Therefore, in sh, eval '(exit $?0)' means eval '(exit 00)', and in csh it means eval '(exit 1)'. The parens indicate that the exit command should be evaluated in a subshell.

sh和csh都将&&理解为执行前一个命令,然后仅在前一个命令退出0时才执行以下命令".因此,只有sh会执行eval 'exec perl -wS $0 ${1+"$@"}'. csh将进入下一行.

Both sh and csh understand && to mean "execute the previous command, then execute the following command only if the previous command exited 0". So only sh will execute eval 'exec perl -wS $0 ${1+"$@"}'. csh will proceed to the next line.

csh将在一行的开头忽略&". (我不确定csh到底意味着什么.它的目的是从Perl的角度使它成为单个表达式.)然后csh继续计算eval 'exec /usr/bin/perl -wS $0 $argv:q'.

csh will ignore "& " at the beginning of a line. (I'm not sure exactly what that means to csh. Its purpose is to make this a single expression from Perl's point of view.) csh then proceeds to evaluate eval 'exec /usr/bin/perl -wS $0 $argv:q'.

这两个命令行非常相似. exec perl表示通过启动perl的副本来替换当前进程. -wS的含义与-w(启用警告)和-S(在$PATH中查找指定的脚本)相同. $0是脚本的文件名.最后,${1+"$@"}$argv:q都生成当前命令行参数的副本(分别在sh和csh中).

These two command lines are quite similar. exec perl means to replace the current process by launching a copy of perl. -wS means the same as -w (enable warnings) and -S (look for the specified script in $PATH). $0 is the filename of the script. Finally both ${1+"$@"} and $argv:q produce a copy of the current command line arguments (in sh and csh, respectively).

它使用${1+"$@"}而不是更常见的"$@"来解决某些古老版本的Bourne shell中的错误.他们是同一回事.您可以在贝内特·托德(Bennett Todd)的解释(复制于gbacon的答案)中阅读详细信息.

It uses ${1+"$@"} instead of the more usual "$@" to work around a bug in some ancient version of the Bourne shell. They mean the same thing. You can read the details in Bennett Todd's explanation (copied in gbacon's answer).

这篇关于解释Perl的“序言"的曲解的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆