我正在重写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";
}
答案 0 :(得分:4)
要从外部命令接收输出,请使用qx
operator,而不是system,它返回wait
返回的程序退出状态。
我建议只将外部程序用于Perl中无法做到的事情,或者很少,当它们大大简化您的工作时。对于其他所有使用Perl的广泛处理能力。
在这种情况下,按grep
过滤dpkg -l
的回复
my @libcUnconfigured = grep { /libc-bin|iF/ } qx(dpkg -l);
print "Do something with $_\n" for @libUnconfigured;
qx
在list context中使用时会返回输出行列表,此处由grep
强制执行。 grep
中的代码块在一个元素上运行,每个元素在默认$_
variable中可用;默认情况下,正则表达式匹配在$_
上完成。代码评估为true的项目通过并作为列表返回,此处分配给数组。
请注意,qx
使用/bin/sh
,通常会降级到系统上的另一个shell。所以小心地把命令放在一起。请参阅链接的文档和$?
in perlvar以进行错误检查。
或者,您可以使用多个模块中的一个。一个不错的是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提供了一种简单,可移植的方式来捕获发送到STDOUT或STDERR的几乎任何内容,无论它是来自Perl,来自XS代码还是来自外部程序。
这里命令形成一个列表,允许system
绕过shell。这是更好的,除非你需要 shell。在这种情况下返回一个(可能是多行)字符串,因此split处理包含信息的行。
其他一些人,在使用能力和使用复杂性方面,IPC::Run3和IPC::Run
另见this entry in perlfaq8。请注意,某些示例中使用的IPC::Open3相当低级。