如何使用 Perl 从文件中提取某些数据?

How to extract certain data using Perl from a file?

我有需要从文件中提取的数据,我现在需要的行是名称、位置和主机。这是提取物的例子。我将如何将这些行放入一个单独的文件中?我有原始文件和我想创建的新文件 input/output 文件,输出文件中包含数千个设备,它们的格式都与我的示例相同。

#!/usr/bin/perl
use strict;
use warnings;
use POSIX qw(strftime);

#names of files to be input output

my $inputfile = "/home/nmis/nmis_export.csv";
my $outputfile = "/home/nmis/nmis_data.csv";
open(INPUT,'<',$inputfile) or die $!;
open(OUTPUT, '>',$outputfile) or die $!;
my @data = <INPUT>;
close INPUT;
my $line="";
foreach $line (@data)
{

======样本提取=======

    **"group" : "NMIS8",
         "host" : "1.2.3.4",
         "location" : "WATERLOO",
         "max_msg_size" : 1472,
         "max_repetitions" : 0,
         "model" : "automatic",
         "netType" : "lan",
         "ping" : 1,
         "polling_policy" : "default",
         "port" : 161,
         "rancid" : 0,
         "roleType" : "access",
         "serviceStatus" : "Production",
         "services" : null,
         "threshold" : 1,
         "timezone" : 0,
         "version" : "snmpv2c",
         "webserver" : 0
      },
      "lastupdate" : 1616690858,
      "name" : "test",
      "overrides" : {}
},
   {
      "activated" : {
         "NMIS" : 1
      },
      "addresses" : [],
      "aliases" : [],
      "configuration" : {
         "Stratum" : 3,
         "active" : 1,
         "businessService" : "",
         "calls" : 0,
         "cbqos" : "none",
         "collect" : 0,
         "community" : "public",
         "depend" : [
            "N/A"
         ],
         "group" : "NMIS8",
         "host" : "1.2.3.5",
         "location" : "WATERLOO",
         "max_msg_size" : 1472,
         "max_repetitions" : 0,
         "model" : "automatic",
         "netType" : "lan",
         "ping" : 1,
         "polling_policy" : "default",
         "port" : 161,
         "rancid" : 0,
         "roleType" : "access",
         "serviceStatus" : "Production",
         "services" : null,
         "threshold" : 1,
         "timezone" : 0,
         "version" : "snmpv2c",
         "webserver" : 0
      },
      "lastupdate" : 1616690858,
      "name" : "test2",
      "overrides" : {}
   },**

因为你有 JSON,你应该用 JSON 解析器解析它。 JSON::PP 是标准 Perl 发行版的一部分。如果你想要更快的东西,你可以从 CPAN 安装其他东西。

更新: 我在回答中加入了 link 到 JSON::PP。您是否遵循 link?如果这样做,您就会看到该模块的文档。这比我在 SO 的答案中包含的更多关于如何使用该模块的信息。

但您可能需要更多高级信息。文档是这样说的:

JSON::PP is a pure perl JSON decoder/encoder

但也许你不知道那是什么意思。所以这是一本入门书。

JSON是一种用于存储复杂数据结构的文本格式。该格式最初用于 Javascript(首字母缩写词代表“JavaScript Object Notation”),但现在它已成为几乎所有编程语言都使用的标准。

您很少想在程序中实际处理 JSON。 JSON 文档只是文本和操作,需要一些复杂的正则表达式。在处理 JSON 时,通常的做法是将 JSON“解码”为程序内部的数据结构。然后,您可以在(可选)将数据结构“编码”回 JSON 之前随意操作数据结构,以便将其写入输出文件(在您的情况下,您不需要这样做您希望输出为 CSV)。

所以 Perl JSON 库几乎只需要做两件事:

  1. 获取一些 JSON 文本并将其解码为 Perl 数据结构
  2. 采用 Perl 数据结构并将其编码为 JSON 文本

如果您查看 JSON::PP documentation,您会发现它包含两个函数,encode_json()decode_json(),它们执行我上面描述的操作。还有一个 OO 接口,但我们不要太快把事情复杂化。

所以你的程序现在需要有以下步骤:

  1. 从输入文件
  2. 读取JSON
  3. 将JSON解码为Perl数据结构
  4. 遍历 Perl 数据结构以提取您需要的项目
  5. 将所需的项目写入您的输出文件(Text::CSV 对此很有用

说了这么多,在我看来 确实是一个更好的主意。

我会用jq for this not Perl. You just need to query a JSON document. That's what jq is for. You can see an example here

我创建的jq查询就是这个,

.[] | {name: .name, group: .configuration.group, location: .configuration.location}

这分解为

.[] # iterate over the array
  | # create a filter to send it to
  {  # that produces an object with the bellow key/values
    .name,
    group: .configuration.group,
    location: .configuration.location
  }

它提供了这样的输出,

{
  "name": "test2",
  "group": "NMIS8",
  "location": "WATERLOO"
}
{
  "name": "test2",
  "group": "NMIS8",
  "location": "WATERLOO"
}

您可以使用它来生成 csv

jq -R '.[] | [.name, .configuration.group, .configuration.location] | @csv' ./file.json

或者生成一个带有 header,

的 csv
jq -R '["name","group","location"], (.[] | [.name, .configuration.group, .configuration.location]) | @csv' ./file.json

您可以为此使用 JSON 发行版。一口气读取整个文件,将整个 JSON 字符串放入标量(而不是将其放入数组并对其进行迭代),然后简单地将字符串解码为 Perl 数据结构:

use warnings;
use strict;

use JSON;

my $file = 'file.json';

my $json_string;

{
    local $/;              # Locally reset line endings to nothing

    open my $fh, '<', $file or die "Can't open file $file!: $!";

    $json_string = <$fh>;  # Slurp in the entire file
}

my $perl_data_structure = decode_json $json_string;