【问题标题】:File processing perl - split produces very small arrays文件处理 perl - split 产生非常小的数组
【发布时间】:2015-08-19 22:26:33
【问题描述】:

美好的一天。我有一个要处理的大文本文件,按如下方式组织:

A
B 87368911
C 165368993    165369000       165369007       165369014       165369021       165369028
D 3299941
E 3221521
F 5909327
G 14740025      14740019        14740031        14740037
H 4446477      4640745

我想将它拆分为数组的哈希,以第一列作为键,如果有的话,将值放在一个可迭代的数组中(在 A 的情况下,没有,如您所见) .为此,我制作了以下代码(略有截断,我显然打开了文件并有周围的代码):

my %resolvedreads;

while (my $line = <IN>) {
    my @thisline = $line =~ m/(\S+)/g;
    $resolvedreads{$thisline[0]} = @thisline[1 .. $#thisline];
    print join "\t", @{$resolvedreads{$thisline[0]}}, "\n";
}

我什至没有真正测试这个,因为它看起来很微不足道。显然我应该有,因为它给了我这个:

Use of uninitialized value $thisline[0] in hash element at resolved_reads_purifier.pl line X-1, <IN> line 1.
Use of uninitialized value $thisline[0] in hash element at resolved_reads_purifier.pl line X, <IN> line 1.
Can't use an undefined value as an ARRAY reference at resolved_reads_purifier.pl line X, <IN> line 1.

我发现自己对此感到有些困惑。进一步调查发现,该行确实是分裂的,但每个数组的长度都是 1 或 2。

那是什么?我觉得我在这里错过了一些基本的东西,我已经无能为力了。尽管在我看来几乎完全相同,但我之前的代码实际上已编译。

【问题讨论】:

  • $line =~ m/(\S+)/g 通常写成split ' ', $line,前面的chomp 两者都不需要
  • 相当,我只是忘记删除 chomp - 我在实际代码中使用它。我尝试了各种拆分变体以及正则表达式来拆分行,它们都抛出了相同的奇怪输出。不过,Awk 处理得很好,所以我认为这不是无法识别的空白字符的问题
  • 另外,第一行后缺少分号。
  • @user3034187:split 的第一个参数通常作为正则表达式处理,但传递 单个文字空间 是一种特殊情况,其作用与 @987654328 相同@, 与 split / / 不同,后者只是在所有出现的空格处拆分

标签: regex perl text field


【解决方案1】:

问题是当文件记录只有一个字段时,$#thisline 为零,所以@thisline[1 .. $#thisline]@thisline[1 .. 0],这是一个空列表。将其分配给给定您undef

的标量

除此之外还有一个问题

$resolvedreads{$thisline[0]} = @thisline[1 .. $#thisline]

因为您将列表分配给标量,并且您通常只会获得列表的最后一个元素$thisline[-1]。此时您应该真正分配一个 数组引用

这就是我将如何编码您的问题

use strict;
use warnings;

my %resolvedreads;

while ( <DATA>) {
    my ($key, @values) = split;
    next unless defined $key;        # Skip blank records
    $resolvedreads{$key} = \@values;
}

use Data::Dump;
dd %resolvedreads;

__DATA__
A
B 87368911
C 165368993    165369000       165369007       165369014       165369021       165369028
D 3299941
E 3221521
F 5909327
G 14740025      14740019        14740031        14740037
H 4446477      4640745

输出

{
  A => [],
  B => [87368911],
  C => [165368993, 165369000, 165369007, 165369014, 165369021, 165369028],
  D => [3299941],
  E => [3221521],
  F => [5909327],
  G => [14740025, 14740019, 14740031, 14740037],
  H => [4446477, 4640745],
}

【讨论】:

    【解决方案2】:

    所以我看到了几件事。上面提到的分配数组时的标量与列表上下文。另一件事是您的切片 [1...#@array] 以“1”开头,但 A 行不存在索引 1,因此您的错误消息。这是工作代码:

    use Modern::Perl '2013';
    use Data::Dumper;
    
    my $text = 'A
    B 87368911
    C 165368993    165369000       165369007       165369014       165369021       165369028
    D 3299941
    E 3221521
    F 5909327
    G 14740025      14740019        14740031        14740037
    H 4446477      4640745';
    
    my $fh;
    open($fh, '<', \$text);
    
    my %resolvedreads;
    
    while (my $line = <$fh>) {
      chomp $line;
      my @thisline = $line =~ m/(\S+)/g;
      my $index    = shift @thisline;
      $resolvedreads{$index} = \@thisline;
    
    }
    
    say Dumper(\%resolvedreads);
    

    【讨论】:

    • 好吧,现在我只是觉得自己很愚蠢。非常感谢,我很确定它做到了。
    【解决方案3】:
    $resolvedreads{$thisline[0]} = @thisline[1 .. $#thisline];
    

    在标量上下文中将一个数组赋给一个哈希值,实际上和

    $resolvedreads{$thisline[0]} = scalar @thisline[1 .. $#thisline];
    

    $resolvedreads{$thisline[0]} = $#thisline;

    $resolvedreads{$thisline[0]} = $thisline[$#thisline];
    

    从您帖子的其余部分看来,您想为哈希值分配一个数组引用

    $resolvedreads{$thisline[0]} = [ @thisline[1 .. $#thisline] ];
    

    同样,您可以将列表分配给列表上下文中的列表

    @{$resolvedreads{$thisline[0]}} = @thisline[1 .. $#thisline];
    

    【讨论】:

    • 我很欣赏您的回复(听起来这应该可以解决我的“小数组”问题),但由于未初始化的值,它仍然无法编译。你对此有什么想法吗?一样的感谢
    • 跳过只有空格的输入行?
    • 应该没有,但我有一个公牛
    • @thisline[1 .. $#thisline] 不是数组,而是切片。 Slices in scalar context return the last item of the slice.
    猜你喜欢
    • 2021-12-30
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多