【问题标题】:How to extract certain data using Perl from a file?如何使用 Perl 从文件中提取某些数据?
【发布时间】:2021-08-15 23:58:09
【问题描述】:

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

#!/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 吗?它看起来像。
  • 是的 - 所以我需要解析数据
  • 我不会为此使用 Perl,我会使用 jq
  • 您能否请update the question 包含您输入文件的准确 内容?我认为@user157251 的解决方案假定您有一个 JSON 对象数组,但您当前的示例实际上并不包含数组。

标签: json perl


【解决方案1】:

我会使用 jq 而不是 Perl。您只需要查询一个 JSON 文档。这就是 jq 的用途。你可以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

或者这样生成带有标题的csv,

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

【讨论】:

  • 有没有办法将其放入带有名称、组、位置标题的 CSV 中?我真正追求的是名称、组、位置作为标题以及下面的 test2、NMIS8、WATERLOO 的信息
  • 太好了,我安装了 JQ,我不熟悉如何使用它,如何将它添加到我可以使用 cron 作业运行的脚本中?本质上,我需要指定运行它的文件并告诉它使用 jq。输入输出在原帖。
  • 我给了你上面的命令在更新中运行。而已。只需jq -R '["name","group","location"], (.[] | [.name, .configuration.group, .configuration.location]) | @csv' ./file.json。只需将其重定向到新的 csv。 &gt; my.csv 或任何 jq -R '["name","group","location"], (.[] | [.name, .configuration.group, .configuration.location]) | @csv' ./file.json &gt; my.csv
  • 是的,但是我如何将该命令插入到我当前的脚本中而不会出现语法错误
  • 实际运行命令并得到 jq: error (at ./nmis_export.csv:80996): Cannot iterate over string (" \...) jq: error (at ./nmis_export.csv: 80997): 无法迭代字符串 (" },")
【解决方案2】:

您可以为此使用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;

【讨论】:

    【解决方案3】:

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

    更新:我在回答中包含了指向 JSON::PP 的链接。你有没有点击那个链接?如果你这样做了,你就会看到该模块的文档。这比我在 SO 的答案中包含的有关如何使用该模块的信息更多。

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

    JSON::PP 是一个纯 perl JSON 解码器/编码器

    但也许你不知道这意味着什么。所以这里有一个入门。

    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. 从输入文件中读取 JSON
    2. 将 JSON 解码为 Perl 数据结构
    3. 遍历 Perl 数据结构以提取您需要的项目
    4. 将所需项目写入您的输出文件(Text::CSV 将对此很有用

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

    【讨论】:

    • 谢谢!您将如何将其与代码联系起来?使用 JSON::PP 那么我将如何使用它来提取我需要输出的字段,抱歉有点新的脚本。
    • @Calarian 如果你想使用Perl,你需要学习Perl;只是要求 StackOverflow 上的人编写您的代码并不会减少它。 JSON::PP 的decode_json 返回一个引用;您应该知道如何处理它。
    • @Calarian:恐怕达达是正确的。如果您需要编写一些 Perl,您要么需要花时间学习 Perl,要么需要聘请已经了解 Perl 的人。但是,我在答案中添加了一些可能对您有所帮助的信息。
    猜你喜欢
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多