将 Bash 翻译成 Perl

Translating Bash to Perl

我正在用 Perl 重写 bash 脚本。

原始脚本检查 Linux 包是否处于 未配置 状态,如果是,则删除并重新安装它。

#!/bin/bash
if [[ $(dpkg -l | grep libc-bin | grep iF) || $(dpkg -l | grep libc-dev-bin | grep iU) ]] ; then
    echo "do something"
fi

我开始看看我是否可以使用系统调用并将它们存储为变量,然后只是 运行 这些多个变量的 if 语句。这似乎没有用。

#!/usr/bin/perl

my $libcUnconfigured    = system("dpkg -l | grep libc-bin | grep iF");
my $libcDevUnconfigured = system("dpkg -l | grep libc-dev-bin | grep iF");

if ( $libcUnconfigured || $libcDevUnconfigured ) {
    print "Do something";
}

为了接收来自外部命令的输出,请使用 qx operator, not system,其中 return 程序的退出状态为 return 由 wait 编辑。

我建议仅将外部程序用于您无法在 Perl 中完成的事情,或者在极少数情况下,当它们极大地简化您的工作时。对于所有其他方面,请使用 Perl 广泛的处理能力。

在这种情况下,通过 grep

dpkg -l 过滤 return
my @libcUnconfigured = grep { /libc-bin|iF/ } qx(dpkg -l);

chomp @libcUnconfigured;

print "Do something with $_\n" for @libUnconfigured;

qx return 是在 list context, here imposed by grep. The code block in grep is run on an element at a time where each is available in the default $_ variable 中使用时的输出行列表;正则表达式匹配默认在 $_ 上完成。代码评估为 true 的项目通过并 returned 作为列表,此处分配给数组。

请注意 qx 使用 /bin/sh,通常在您的系统上归入另一个 shell。所以仔细地把命令放在一起。请参阅链接文档和 $? in perlvar 进行错误检查。

returned 列表中的每一行输出都带有换行符,假设对这些文件名进行了一些重要的处理,我删除了换行符。 (当然不需要 chomp 单独打印。)

或者,您可以选择多个模块中的一个。一个不错的是 Capture::Tiny

use warnings;
use strict;
use feature 'say';

use Capture::Tiny qw(capture);

my @cmd = qw(dpkg -l);

my ($stdout, $stderr) = capture {
    system (@cmd);
};

warn "Error with @cmd: $stderr" if $stderr;

say "Do something with $_" for (split /\n/, $stdout);

因为它简洁的语法,它给我们带来的错误,以及它能够 运行 几乎任何代码

Capture::Tiny provides a simple, portable way to capture almost anything sent to STDOUT or STDERR, regardless of whether it comes from Perl, from XS code or from an external program.

这里的命令是一个列表,是什么让system绕过了shell。这样更好,除非您需要 shell。 return 在这种情况下是一个(可能是多行的)字符串,因此 split 用于处理包含包信息的行。

其他一些,在增加使用的能力和复杂性方面,是 IPC::Run3 and IPC::Run

另请参阅 this entry in perlfaq8. Note that IPC::Open3 在一些示例中使用的是相当低级的。