使用Perl读取非分隔文本文件

使用Perl读取非分隔文本文件,perl,Perl,我有一个文件,它有一个标准的输入,但它的形式我以前从未尝试读入Perl程序 该文件的格式如下: 净数量分配 编号xxx.xxx.xxx.xxx 表30中的网络掩码 类型IP 使用状态 说明mpirpd cjdn 票据管理 条目Id 0000000000 26450 提交人约翰·多伊 创建日期2009-07-01-13:55:24 内部联系方式/555-555-5555 联系人Id CON-000028508 净分配数 编号xxx.xxx.xxx.xxx 格式32中的网络掩码 类型IP 使用状态

我有一个文件,它有一个标准的输入,但它的形式我以前从未尝试读入Perl程序

该文件的格式如下:

净数量分配
编号xxx.xxx.xxx.xxx
表30中的网络掩码
类型IP
使用状态
说明mpirpd cjdn
票据管理
条目Id 0000000000 26450
提交人约翰·多伊
创建日期2009-07-01-13:55:24
内部联系方式/555-555-5555
联系人Id CON-000028508
净分配数
编号xxx.xxx.xxx.xxx
格式32中的网络掩码
类型IP
使用状态
说明开关Lo0--开关未命名
Lan管理环回和链路的注释
条目Id 0000000000 32710
提交人约翰·多伊
创建日期2015-11-25-10:59:27
最后由JohnDoe修改
修改日期2015-11-25-11:30:06
内部联系方式/555-555-5555
联系人Id CON-000028508
净分配数
编号xxx.xxx.xxx.xxx
格式32中的网络掩码
类型IP
使用状态
说明mplsfe9集线器
区域mpls
条目Id 0000000000 24150
提交人Russ Reilly
创建日期2007-05-02-18:26:20
最后由JohnDoe修改
修改日期2013-05-06-19:09:37
联系人姓名ITG内部
联系电话555-555-5555
联系电子邮件me@home.com
并非总是使用所有字段(例如:联系人姓名和联系人电话可能在下一条记录中丢失)

我不一定需要字段标题,因为它们始终位于每个记录的相同位置


我相信这是以前做过的,可能有一个简单的解决方案,所以在我重新创建轮子之前,我会问这个问题

这在概念上很简单,但有点乏味。此类解析解决方案的规范版本如下所示:

#!/usr/bin/perl
my $all = {};  # A hash to hold all number entries indexed by IP
my $cur = {};  # A hash to hold the current entry we are parsing
while(<>)
{
    chomp;
    if (my ($ip) = /^Number\s+(.*)/)
    {
        # If we have a current entry, save it in the $all hash
        $all->{$cur->{number}} = $cur if ($cur->{number});

        $cur = {};
        $cur->{number} = $ip;
    }
    elsif (my ($mask) = /^Netmask in \/## Form\s+(\d+)/)
    {
        $cur->{mask} = $mask;
    }
    elsif ... # Handle remaining input line types, saving what you want in $cur
}
# This is to save the last entry
$all->{$cur->{number}} = $cur if ($cur->{number});

# Your code to process the accumulated entries
...
#/usr/bin/perl
我的$all={};#用于保存由IP索引的所有数字项的哈希
我的$cur={};#用于保存我们正在分析的当前项的哈希
while()
{
咀嚼;
如果(我的($ip)=/^Number\s+(.*)/)
{
#如果有当前条目,请将其保存在$all散列中
$all->{$cur->{number}}=$cur if($cur->{number});
$cur={};
$cur->{number}=$ip;
}
elsif(my($mask)=/^Netmask,格式为\/##\ s+(\d+/)
{
$cur->{mask}=$mask;
}
elsif…#处理剩余的输入行类型,将所需内容保存在$cur中
}
#这是为了保存最后一个条目
$all->{$cur->{number}}=$cur if($cur->{number});
#处理累积条目的代码
...

这在概念上很简单,但有点乏味。此类解析解决方案的规范版本如下所示:

#!/usr/bin/perl
my $all = {};  # A hash to hold all number entries indexed by IP
my $cur = {};  # A hash to hold the current entry we are parsing
while(<>)
{
    chomp;
    if (my ($ip) = /^Number\s+(.*)/)
    {
        # If we have a current entry, save it in the $all hash
        $all->{$cur->{number}} = $cur if ($cur->{number});

        $cur = {};
        $cur->{number} = $ip;
    }
    elsif (my ($mask) = /^Netmask in \/## Form\s+(\d+)/)
    {
        $cur->{mask} = $mask;
    }
    elsif ... # Handle remaining input line types, saving what you want in $cur
}
# This is to save the last entry
$all->{$cur->{number}} = $cur if ($cur->{number});

# Your code to process the accumulated entries
...
#/usr/bin/perl
我的$all={};#用于保存由IP索引的所有数字项的哈希
我的$cur={};#用于保存我们正在分析的当前项的哈希
while()
{
咀嚼;
如果(我的($ip)=/^Number\s+(.*)/)
{
#如果有当前条目,请将其保存在$all散列中
$all->{$cur->{number}}=$cur if($cur->{number});
$cur={};
$cur->{number}=$ip;
}
elsif(my($mask)=/^Netmask,格式为\/##\ s+(\d+/)
{
$cur->{mask}=$mask;
}
elsif…#处理剩余的输入行类型,将所需内容保存在$cur中
}
#这是为了保存最后一个条目
$all->{$cur->{number}}=$cur if($cur->{number});
#处理累积条目的代码
...

我建议使用哈希数组作为您所展示文件的理想数据结构

我们将设置为
,将两个或多个连续的空行视为一个空行。然后,在每个记录中,我们只需将每行
拆分为两个或多个空格,这将保留包含空格的键。
拆分
限制为总共2个字段,以防止为包含两个或多个连续空格的值创建其他字段(例如,
ITG INTERNAL


我建议使用散列数组作为您提供的文件的理想数据结构

我们将设置为
,将两个或多个连续的空行视为一个空行。然后,在每个记录中,我们只需将每行
拆分为两个或多个空格,这将保留包含空格的键。
拆分
限制为总共2个字段,以防止为包含两个或多个连续空格的值创建其他字段(例如,
ITG INTERNAL


您试图将这些数据解析成什么样的结构?通常我会使用数组进行哈希运算。在这种情况下,我的密钥将是数字字段,该字段在整个文件中应该是唯一的,数组将是在下一个数字字段之前的字段。因此,您想使用该字段处理许多文件吗?每个都将使用数组ref填充自己的数字键?(如果它有一个hash ref,由字段名键入,可能更可读。)如果它是一个数组,您可以将。。。当没有此类记录时,是否为零/空字符串?这应该(相对)简单,你试过什么吗?它不起作用了吗?或者你不知道怎么做?是你在一个文件中显示的内容,还是你在显示多个(3)文件?是否每一节“网络编号Ass…”都有自己的(唯一)编号?这是一个文件中3条记录的样本。该文件实际上包含1000条记录。您试图将这些数据解析成什么样的结构?通常我会使用数组进行哈希运算。在这种情况下,我的密钥将是数字字段,该字段在整个文件中应该是唯一的,数组将是在下一个数字字段之前的字段。因此,您想使用该字段处理许多文件吗?每个都将使用数组ref填充自己的数字键?(如果它有一个hash ref,由字段名键入,可能更可读。)如果它是一个数组,您可以将。。。当没有此类记录时,是否为零/空字符串?这应该(相对)简单,你试过什么吗?它不起作用还是不起作用
[
  {
    "Contact-Data"        => "INTERNAL/555-555-5555",
    "Contact-Id"          => "CON-000028508",
    "Create-date"         => "2009-07-01-13:55:24",
    "Description"         => "mpirpd-cjdn",
    "Entry-Id"            => "000000000026450",
    "Netmask in /## Form" => 30,
    "Notes"               => "mgmt",
    "Number"              => "xxx.xxx.xxx.xxx",
    "Status"              => "InUse",
    "Submitter"           => "John Doe",
    "Type"                => "IP",
  },
  {
    "Contact-Data"        => "INTERNAL/555-555-5555",
    "Contact-Id"          => "CON-000028508",
    "Create-date"         => "2015-11-25-10:59:27",
    "Description"         => "switch Lo0 -- switch unnamed",
    "Entry-Id"            => "000000000032710",
    "Last-modified-by"    => "John Doe",
    "Modified-date"       => "2015-11-25-11:30:06",
    "Netmask in /## Form" => 32,
    "Notes"               => "Reverved for Lan Management Loop Backs and links",
    "Number"              => "xxx.xxx.xxx.xxx",
    "Status"              => "InUse",
    "Submitter"           => "John Doe",
    "Type"                => "IP",
  },
  {
    "Area"                => "mpls",
    "Contact E-mail"      => "me\@home.com",
    "Contact Name"        => "ITG  INTERNAL",
    "Contact Phone"       => "555-555-5555",
    "Create-date"         => "2007-05-02-18:26:20",
    "Description"         => "mplsfe9-hub",
    "Entry-Id"            => "000000000024150",
    "Last-modified-by"    => "John Doe",
    "Modified-date"       => "2013-05-06-19:09:37",
    "Netmask in /## Form" => 32,
    "Number"              => "xxx.xxx.xxx.xxx",
    "Status"              => "InUse",
    "Submitter"           => "Russ Reilly",
    "Type"                => "IP",
  },
]