Perl 脚本处理输入文件并实现期望的输出

Perl script process input file and achieve desire output

这是 Perl 脚本,读取包含 IP 和 stsco 名称的文件。我将项目溢出到两列并使用第二个 c2 进行处理。并调用另一个 Perl 脚本来 return 我需要的值并将其打印在文件中。 如果你看到我的输入文件第 8 行 ( 10.22.1.50 stsco25527020 ) 没有采用这个值不知道为什么,可能是因为 IP 和 stsco 之间有空格。 你能帮我看看如何实现期望的输出吗?如果您知道为什么我的脚本没有在第 8 行中取值,也将不胜感激

use strict;
use warnings;
use Data::Dumper;

my $input_file = 'status.txt';
my $output_file = 'status_results.txt';
open my $fh, '<', $input_file or die $!;
open my $wfh, '>', $output_file or die $!;

while (<$fh>){
    chomp;
    next if /^\</;
    next if /^\s*$/;

    my ($c1, $c2) = split /\s/, $_;
    my $stssysId = "$c2";
    $stssysId = `/bin/call_api.pl --op=stssys_id --kv stssys_id=$stssysId | grep Status`;
    print $wfh "$c2\t$stssysId\n";
}

status.txt(这是输入文件)

10.22.10.12   stsco28698039
10.22.13.38   stsco28016005
10.22.11.23   stsco28497006
10.22.10.15   stsco28598003
10.22.18.12   stsco28534122
10.22.10.15   stsco28598002
10.22.12.10   stsco26944008
10.22.1.50            stsco25527020
10.22.70.21   stsco28698022
10.22.15.22   stsco28698024
10.24.70.74   stsco9372006
10.24.54.16   stsco28698020

status_results(输出文件)

stsco28698039         "Status" : "Active",

stsco28016005         "Status" : "Active",

stsco28497006         "Status" : "Active",

stsco28598003         "Status" : "Active",

stsco28534122         "Status" : "Active",

stsco28598002         "Status" : "Active",

stsco26944008         "Status" : "Active",


stsco28698022
stsco28698024
stsco9372006
stsco28698020
stsco28598004         "Status" : "Active",

想要输出 - 或结果 - (我想删除“状态”:“和')

stsco28698039         Active

stsco28016005         Active

stsco28497006         Active

stsco28598003         Active

stsco28534122         Active

stsco28598002         Active

stsco26944008         Active


stsco28698022
stsco28698024
stsco9372006
stsco28698020
stsco28598004         Active

尝试拆分一个或多个空白字符而不是单个空白字符:

my ($c1, $c2) = split /\s+/, $_;

要使 $stsysId 只有活动部分:

#Matches any of the characters '"', ",", ":", space, or the word Status
$stsysId =~ s/[",: ]|Status//g;

#[0] is "" (the empty string), [1] is Status, [2] is " : ", [3] is "Active"
$stsysId = (split '"', $stsysId)[3];
$stsysId //= ""; #Perl 5.10.0+
$stsysId = "" unless defined $stsysId; #older perls

#Match two double quote delimited strings, possibly with characters in between.
$stsysId =~ m/"([^"]+)".*?"([^"]+)"/;
$stsysId =  if defined ;

请调查以下代码片段是否符合您的任务。

可以利用更精确的正则表达式来处理输入数据,过滤出想要的输入数据。通过这样做,代码变得更短并且更错误抵抗。随意尝试使用 regex 来匹配输入文件的内容。

在这种特殊情况下 split 没有参数(特殊情况等同于 /\s+/)将做你想做的事——将一个字符串分成两个值。最好为值分配更合适的名称,如 ipnode.

使用反引号获取状态可能不是最佳选择(尽管它可以满足您的要求)。您可以在管道中使用外部程序过滤掉不需要的参数,或者在 list context.

中使用反引号

Perl 提供 qx(command argument .. argument) 作为反引号的替代方法,使代码更易于阅读。不要害羞尝试使用此选项。 perl qx

相反,您可以对提供节点状态的命令使用 open on a pipe。这将允许您将命令的输出作为文件和 filter/capture 感兴趣的信息与 perl 的指令一起阅读。

或者作为替代选项,您可以使用 system 带有参数数组的命令调用(更安全的调用形式)。

在提供的代码示例中,为简单起见,节点的 $state 是通过正则表达式捕获的。按照设计,它应该捕获节点的状态 - 由于缺少 call_api.pl 实用程序,这部分未经过测试。

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

my $re = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\s+stsco\d+/;

while( <> ) {
    next unless /$re/;
    my($ip,$node) = split;
    my $status = `/bin/call_api.pl .....`;
    my($state) = $status =~ /^$node\s+"Status" : "(\w+)"/;
    say  join("\t",$node,$state);
}

运行 作为 script.pl nodes.txt > status.txt

参考: split, regex, system, qx, open null filehandle <>

在您的脚本调用第二个脚本后修改字符串以删除不需要的部分:

  $stssysId =~ s/Status : //;
  $stssysId =~ s/\"//g;