'`' 字符在 Perl 中有什么作用? [英] What does the '`' character do in Perl?

查看:52
本文介绍了'`' 字符在 Perl 中有什么作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 Perl 来读取文件的每一行.我使用命令行工具来调用服务,我注意到一些有趣的功能,我无法弄清楚如何搜索.我将调用服务的命令分配给变量 $cmd.如果我稍后在代码中引用 $cmd 它会打印出命令行参数,但是如果我将它称为 `$cmd`,它会给出输出运行服务.

I was using Perl to read through each line of a file. I used a command line tool to call a service, and I noticed some interesting functionality that I can't figure out how to search for. To the variable $cmd I assigned the command that invokes the service. If I refer to $cmd later in the code it prints out the command line argument, but if I refer to it as `$cmd`, however, it gives the output from running the service.

对此有何解释?

推荐答案

它就像 shell 中的反引号一样,这就是它被称为反引号的原因.有关详细信息,请参阅 sh(1).它仅捕获标准输出,不捕获其他任何内容.它将 $? 变量设置为 16 位等待状态字.

It works just like backquotes in the shell, which is why it is called that. See sh(1) for details. It captures the standard output alone, and nothing else. It sets the $? variable to the 16-bit wait status word.

这在 perlop(1) 中都有解释手册页:

This is all explained in the perlop(1) manpage:

qx/STRING/
`STRING`
一个(可能)内插的字符串,然后作为带有 /bin/sh 或其的系统命令执行相等的.Shell 通配符、管道和重定向会受到尊重.收集的标准输出命令被返回;标准误差不受影响.在标量上下文,它作为单个返回(可能多行)字符串,或 undef 如果命令失败.在列表上下文中,返回一个行列表(但是你已经用 $/ 定义了行,或者$INPUT_RECORD_SEPARATOR),或者空列表,如果命令失败.

qx/STRING/
`STRING`
A string which is (possibly) interpolated and then executed as a system command with /bin/sh or its equivalent. Shell wildcards, pipes, and redirections will be honored. The collected standard output of the command is returned; standard error is unaffected. In scalar context, it comes back as a single (potentially multi-line) string, or undef if the command failed. In list context, returns a list of lines (however you’ve defined lines with $/ or $INPUT_RECORD_SEPARATOR), or the empty list if the command failed.

因为反引号不影响标准错误:使用shell 文件描述符语法(假设 shell支持这一点)如果你想解决这个问题.至捕获命令的 STDERRSTDOUT 合并在一起:

Because backticks do not affect standard error: use shell file descriptor syntax (assuming the shell supports this) if you care to address this. To capture a command’s STDERR and STDOUT merged together:

$output = `cmd 2>&1`;

捕获命令的STDOUT但丢弃它的STDERR:

To capture a command’s STDOUT but discard its STDERR:

$output = `cmd 2>/dev/null`;

捕获命令的STDERR但丢弃它的STDOUT(这里的顺序很重要):

To capture a command’s STDERR but discard its STDOUT (ordering is important here):

$output = `cmd 2>&1 1>/dev/null`;

交换命令的 STDOUTSTDERR 以便捕获 STDERR 但让它的 STDOUT 出来旧的STDERR:

To exchange a command’s STDOUT and STDERR in order to capture the STDERR but leave its STDOUT to come out the old STDERR:

$output = `cmd 3>&1 1>&2 2>&3 3>&-`;

读取命令的 STDOUT 和它的 STDERR分开,最容易分开重定向到文件,然后从这些文件中读取程序完成:

To read both a command’s STDOUT and its STDERR separately, it’s easiest to redirect them separately to files, and then read from those files when the program is done:

 system("program args 1>program.stdout 2>program.stderr");

命令使用的STDIN文件句柄是继承的来自 Perl 的 STDIN.例如:

The STDIN filehandle used by the command is inherited from Perl’s STDIN. For example:

open(BLAM, "blam")     || die "$0: can't open blam: $!";
open (STDIN, "<&BLAM") || die "$0: can't dup BLAM: $!";
print `sort`;

将打印文件blam的排序内容.

will print the sorted contents of the file blam.

使用单引号作为分隔符保护命令来自 Perl 的双引号插值,将内容传递给改为shell:

Using single-quote as the delimiter protects the command from Perl’s double-quote interpolation, passing the contents on to the shell instead:

$perl_info  = qx(ps $$);    # that's Perl's $$
$shell_info = qx'ps $$';    # that's the new shell's $$

该字符串的评估方式完全取决于系统上的命令解释器.在大多数平台,你将不得不保护外壳元字符,如果您希望它们按字面处理.这在实践中很难做到,因为目前还不清楚哪些字符需要转义,或者如何转义.请参阅 perlsec 了解forkexec安全地模拟反引号.在某些平台上(特别是类似 DOS 的平台),shell可能无法处理多行命令,所以在字符串中放置换行符可能不会给你什么你要.您可能能够评估多个命令在一行中,用命令分隔符,如果你的 shell 支持那(例如 ; 在许多 Unix shell 上;& 在 WindowsNT CMD.COM 外壳).

How that string gets evaluated is entirely subject to the command interpreter on your system. On most platforms, you will have to protect shell metacharacters if you want them treated literally. This is in practice difficult to do, as it’s unclear which characters need escaping, or how. See perlsec for a clean and safe example of a manual fork and exec to emulate backticks safely. On some platforms (notably DOS-like ones), the shell may not be capable of dealing with multiline commands, so putting newlines in the string may not get you what you want. You may be able to evaluate multiple commands in a single line by separating them with the command separator character, if your shell supports that (e.g. ; on many Unix shells; & on the Windows NT CMD.COM shell).

从 v5.6.0 开始,Perl 尝试刷新所有在启动子进程之前打开的文件用于输出过程,但在某些情况下可能不支持平台(参见 perlport(1)).为了安全起见,您可能需要设置 $| ($AUTOFLUSH 英文) 或调用任何打开的 IO::Handleautoflush 方法把手.

Beginning with v5.6.0, Perl attempts to flush all files opened for output before starting the child process, but this may not be supported on some platforms (see perlport(1)). To be safe, you may need to set $| ($AUTOFLUSH in English) or call the autoflush method of IO::Handle on any open handles.

请注意某些命令 shell 可能会设置限制在命令行的长度上.你必须确保您的字符串在任何之后都不会超过此限制必要的插值.请参阅特定于平台的发行说明,了解有关您的特定环境.

Beware that some command shells may place restrictions on the length of the command line. You must ensure your strings don’t exceed this limit after any necessary interpolations. See the platform-specific release notes for more details about your particular environment.

使用此运算符可能会导致程序难以移植,因为 shell 命令调用因系统而异,实际上可能不存在根本.例如,type 命令下的POSIX shell 与 type 命令有很大不同在DOS下.这并不意味着你应该离开在正确的情况下避免反引号的方法完成某事.Perl 是一种胶水语言,它粘合在一起的东西之一是命令.只需了解您将得到什么自己进去.

Using this operator can lead to programs that are difficult to port, because the shell commands called vary between systems, and may in fact not be present at all. As one example, the type command under the POSIX shell is very different from the type command under DOS. That doesn't mean you should go out of your way to avoid backticks when they’re the right way to get something done. Perl was made to be a glue language, and one of the things it glues together is commands. Just understand what you’re getting yourself into.

有关更多讨论,请参阅 I/O 运算符.

See I/O Operators for more discussion.

以下是使用反引号获取管道中第一个元素的退出状态的简单示例:

Here’s a simple example of using backticks to get the exit status of the first element in a pipeline:

$device = q(/dev/rmt8);
$dd_noise = q(^[0-9]+\+[0-9]+ records (in|out)$);
$status = `exec 3>&1; ((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |  egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`;

<小时>

编辑

好吧,所以也许这不是那个简单的例子.:) 但这是一个.


EDIT

Well ok then, so maybe that wasn’t that simple an example. :) But this one is.

我想推荐 Capture::TinyCPAN 模块 作为一种更简单的方式来管理通常使用反引号运行的外部命令的输出.它有优点也有缺点,但我觉得对很多人来说,优点大于任何可以争论的缺点L

I’d like to recommend the Capture::Tiny CPAN module as a simpler way to manage the output from external commands that you would normally run using backquotes. It has advantages and disadvantages, but I feel that for many people, the advantages outweigh any arguable disadvantageL

  • 优势是,您可以完成所有这些工作,而无需像上一个示例那样深入了解文件描述符重定向的神秘奥秘.

  • The advantage is that you get to do all this without requiring deep knowledge of arcane mysteries of file-descriptor redirection the way the previous example did.

缺点是另一个非核心依赖项 - 您必须从 CPAN 安装其他东西.

The disadvantage is it’s yet another non-core dependency — something else you have to install from CPAN.

这对你所得到的来说真的不错.

That’s really not bad for what you get.

这是一个多么容易的例子:

Here’s an example of how easy it is:

姓名

Capture::Tiny - 捕获标准输出和来自 Perl 的 STDERR、XS 或外部程序

概要

    use Capture::Tiny qw/capture tee capture_merged tee_merged/;

     ($stdout, $stderr) = capture {
        # your code here
      };

     ($stdout, $stderr) = tee {
        # your code here
      };

     $merged = capture_merged {
        # your code here
      };

     $merged = tee_merged {
        # your code here
      };

描述

Capture::Tiny 提供了一种简单、便携的方式来捕获发送的任何内容到 STDOUT 或 STDERR,无论它是否来自 Perl,来自 XS 代码或来自外部程序.或者,输出可以被 teed,以便它在传递到原始句柄时被捕获.是的,它甚至适用于 Windows.不要猜测在任何特定情况下要使用十几个捕获模块中的哪一个,只需使用这个.

Capture::Tiny provides a simple, portable way to capture anything sent to STDOUT or STDERR, regardless of whether it comes from Perl, from XS code or from an external program. Optionally, output can be teed so that it is captured while being passed through to the original handles. Yes, it even works on Windows. Stop guessing which of a dozen capturing modules to use in any particular situation and just use this one.

这样,不是更容易吗?

这篇关于'`' 字符在 Perl 中有什么作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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