根据关键词将文件内容分割成两个数组

3

我有一个文件,其中有类似以下内容:

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);。但我仍需要其他四行以便将其放入另一个数组。
那么我该如何根据关键词拆分文件呢?

第一部分做得很好。现在你只需要再为第二部分重复一遍。就是这样。 - JB.
6个回答

5

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

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

这将以两个块读取文件,有效地在.endm\n处分割。注意,chomp会从字符串末尾删除$/的值。这里的map语句只是按换行符分割输入并将其放入数组引用中。生成的数组是二维的,如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;

感谢您的努力!谢谢。 - Rancho
它能工作...但对于我基本的Perl知识来说看起来很复杂 :) 我需要深入了解数据转储和映射。 - Rancho
这并不是很复杂。Data::Dumper 是一个以有组织的方式打印数据的模块。map CODE LIST 只是一种循环,其中 CODE 的返回值会针对 LIST 中的每个元素给出。因此,map $_ * 2, (1,2,3) 将返回列表 2,4,6 - TLP
顺便说一下,@a = map [ split /\n/ ], @a; 也可以写成 $_ = [ split /\n/ ] for @a; - Hynek -Pichi- Vychodil

2
#!/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'
        ];

非常感谢。感谢您的帮助! - Rancho

2

我建议简单处理,按以下方式操作:

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

@Rancho 你在等什么呢?;-) - JB.

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;}时,它打印整个数组而不是逐行打印。 - Rancho
你是不是忘了加换行符? foreach $line (@array1) {print $line."\n";} - Jean
哦,抱歉不是真的。我在分割字符串时跳过了 \n 并直接将其赋值给 $temp[0]。它可以正常工作。对不起和谢谢 :) - Rancho

1
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

1

你写代码之前不看文档或教程,是吗?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;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接