【问题标题】:Perl script process input file and achieve desire outputPerl脚本处理输入文件并实现期望输出
【发布时间】:2021-06-02 03:48:55
【问题描述】:

这是 Perl 脚本,读取包含 IP 和 stsco 名称的文件。我将项目溢出到两列并使用第二个 c2 进行处理。并调用另一个 Perl 脚本来返回我需要的值并将其打印到文件中。 如果您看到我的输入文件第 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",

希望输出 - 或结果 -(我想删除 "status" : " 和 ')

stsco28698039         Active

stsco28016005         Active

stsco28497006         Active

stsco28598003         Active

stsco28534122         Active

stsco28598002         Active

stsco26944008         Active


stsco28698022
stsco28698024
stsco9372006
stsco28698020
stsco28598004         Active

【问题讨论】:

  • 请注意,status_results.txt 输出文件中的值 stsco28698022、stsco28698024、stsco9372006、stsco28698020 为空,因为没有返回值
  • 我不知道这个脚本的大部分内容在做什么,但是那个 shell 命令会立即在我的大脑中引发每一个危险信号。您将 Perl 变量插入到 shell 指令中,没有转义、没有检查、没有清理,什么都没有。即使您输入中的意外单引号或括号也会将该脚本从轨道中删除,更不用说恶意输入文件了。
  • 您好@SilvioMayolo 感谢您的回复,我正在循环输入文件并查询每个 stsco ID 以检查配置状态是否处于活动状态。就像上面的输出文件一样。我调用一个 api 脚本来告诉我状态是否处于活动状态
  • @Ayad 我们永远不知道 API 脚本的作用。一旦您运行 API 脚本并打印结果以获得所需的输出,我们必须替换(使用正则表达式)变量 $stssysId 中的值 "Status" :

标签: perl


【解决方案1】:

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

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 = $2 if defined $2;

【讨论】:

  • 嗨@Nathan Mills,非常感谢!我用“+”尝试了你的命令并且它有效,我的脚本采用第 8 行中的值 - 现在第二部分已解决,现在我正在尝试实现所需的输出
  • 非常好,非常感谢它有效。我已经实现了根据您的答案添加的所需输出 $stsysId =~ s/[",: ]|Status//g; 它可以工作
【解决方案2】:

请调查以下代码 sn-p 是否符合您的任务。

可以使用更精确的正则表达式来处理输入数据以过滤掉所需的输入数据。通过这样做,代码会变得更短且更防错。随意尝试使用 regex 来匹配输入文件的内容。

在这种特殊情况下,split 不带参数(特殊情况等效于 /\s+/)将执行您想要的操作 - 将字符串拆分为两个值。最好为 ipnode 等值分配更合适的名称。

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

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

相反,您可以将open on a pipe 用于提供节点状态的命令。这将允许您将命令的输出作为文件读取,并使用 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 &gt; status.txt运行

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

【讨论】:

  • 这个很有用,我试试看
【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 2023-03-09
    • 2017-11-21
    • 1970-01-01
    相关资源
    最近更新 更多