【问题标题】:Split file contents into 2 arrays based on a key word根据关键字将文件内容拆分为 2 个数组
【发布时间】:2013-09-26 05:30:47
【问题描述】:

我有一个类似的文件

line1
line2
line3
line4
.endm
line5
line6
line7
line8
.endm

我想在 .endm 处拆分此文件并将内容放入 2 个不同的数组中。输出将是

@array1=(line1,line2,line3,line4);
@array2=(line4,line6,line7,line8);

我尝试过使用

@array = split(".endm",my_file.txt);
print("Array1 = $array[1]\nArray2 = $array[2]\n);

但这只是打印出最后一个 .endm 的行号

我也尝试过类似的东西

#! /usr/intel/bin/perl -w
use strict;

my $count=0;
open(my $fh, "<", "a.txt")|| die "can't open UTF-8 encoded filename: $!";
my @lines = <$fh>;
my @array;

LOOP: foreach my $line (@lines) {
    chomp ($line);
    $count = $count+1;
    push (@array,$line);  
    if ($line =~ m/.endm/) {
        pop (@array);
        last LOOP;
    }
}
print("Array : @array\n");
close $fh;

这个打印 @array=(line1,line2,line3,line4); 但我仍然需要其他 4 行,以便我可以将它放在不同的数组中

那么我该如何根据某个关键字来拆分文件呢?

【问题讨论】:

  • 第一部分已经足够好了。现在你只需要为第二个再做一次。从字面上看。

标签: arrays perl split


【解决方案1】:

如果文件很小,这将起作用。

#!/usr/bin/perl 

use strict;
use warnings;

open(FILE,"input.txt");
my @lines =<FILE>;                 # Reads all lines of the file into an array
my $line  = join('',@lines);       # Join all lines together
my @temp = split(/.endm/,$line);   # Split the line using the keyword
my @array1=split(/\n/,$temp[0]);   # Splits line back 
my @array2=split(/\n/,$temp[1]);   # Splits line back

print @array1;
print "\n";
print @array2;

close(FILE);

【讨论】:

  • 这个问题的一个小问题是,我想再次重用 array1 和 @array2 并对此做一些正则表达式。但是当我使用 foreach $line (@array1) {print $line;它正在打印整个数组而不是一行一行
  • 你忘了放换行符吗? foreach $line (@array1) {print $line."\n";}
  • 哦,对不起,不是真的。我在 split 中跳过了 \n 并直接将其分配给了 $temp[0]。它工作正常。对不起,谢谢:)
【解决方案2】:

我会保持简单并这样做:

my (@array1,@array2);
while ($_ = <>) { chomp; last if $_ eq '.endm'; push @array1, $_ }
while ($_ = <>) { chomp; last if $_ eq '.endm'; push @array2, $_ }

【讨论】:

  • @Rancho 说,你还在等什么? ;-)
【解决方案3】:
use 5.10.0;
use strict;
use warnings;

open( my $fh, '<', 'a.txt' ) or die "can't open filename: $!";

my @arrays;
my $array = [];

while (<$fh>) {
    chomp;
    if (/^\.endm$/) {
        push @arrays, $array;
        $array = [];
        next;
    }
    push @$array, $_;
}

local $, = ",";
say @$_ for @arrays;

$array = [] 是不必要的,但可以提高可读性。并输出:

line1,line2,line3,line4
line5,line6,line7,line8

【讨论】:

    【解决方案4】:

    在编写代码之前,您不会费心阅读文档或教程,是吗? Split 将字符串拆分为数组,而不是将文件拆分为行。

    open INPUT,"<my_file.txt" or die "no such file";
    my @array1;
    my @array2;
    my $ref = \@array1;
    while ( my $line = <INPUT> ) {
      chomp($line);
      if ( $line eq ".endm" ) {
        $ref = \@array2;
      } else {
        push(@$ref,$line);
      }
    }
    print $_ . " " foreach @array1;
    print "\n";
    print $_ . " " foreach @array2;
    

    【讨论】:

      【解决方案5】:
      #!/usr/bin/perl 
      use strict;
      use warnings;
      use Data::Dumper;
      
      open my $fh, '<', 'data.txt' or die "can't open data.txt: $!";
      
      my @array;
      
      $/ = ".endm";
      
      while (<$fh>){
          s/\.endm$//;
          push @array, [split];
      }
      
      print Dumper(@array);
      
      #output
      $VAR1 = [
               'line1',
               'line2',
               'line3',
               'line4'
              ];
      $VAR2 = [
               'line5',
               'line6',
               'line7',
               'line8'
              ];
      

      【讨论】:

      • 非常感谢。感谢您的帮助!
      【解决方案6】:

      如果你有一个固定的字符串作为字段分隔符,你可以设置内置变量$/——输入记录分隔符——来改变Perl的readline()函数读取行的方式。

      perl -MData::Dumper -we '$/=".endm\n"; chomp(@a = <>); 
            @a = map [ split /\n/ ], @a; print Dumper \@a;' file.txt
      

      这将分两块读取文件,有效地分割.endm\n。请注意,chomp 会从字符串末尾删除 $/ 的值。此处的map 语句只是将输入拆分为换行符并将其放入数组 ref 中。结果数组是二维的,如Data::Dumper 输出所示:

      输出:

      $VAR1 = [
                [
                  'line1',
                  'line2',
                  'line3',
                  'line4'
                ],
                [
                  'line5',
                  'line6',
                  'line7',
                  'line8'
                ]
              ];
      

      完整版如下:

      use strict;
      use warnings;
      use Data::Dumper;
      
      $/ = ".endm\n";
      chomp(my @a = <>);
      @a = map [split /\n/], @a;
      print Dumper \@a;
      

      【讨论】:

      • 感谢您的努力!谢谢
      • 它可以工作..但我的基本 perl 知识看起来很​​复杂 :) 我需要深入研究数据转储器和映射
      • 没那么复杂。 Data::Dumper 是一个以有组织的方式打印数据的模块。 map CODE LIST 只是一种循环,其中 CODE 的返回值是针对 LIST 中的每个元素给出的。所以map $_ * 2, (1,2,3) 将返回列表2,4,6
      • 顺便说一下@a = map [ split /\n/ ], @a;$_ = [ split /\n/ ] for @a;一样可以写。
      猜你喜欢
      • 2013-01-09
      • 1970-01-01
      • 2017-05-15
      • 1970-01-01
      • 2015-11-14
      • 1970-01-01
      • 1970-01-01
      • 2021-06-08
      • 1970-01-01
      相关资源
      最近更新 更多