【问题标题】:Perl - Regex in CSVPerl - CSV 中的正则表达式
【发布时间】:2013-08-05 20:58:50
【问题描述】:

以下问题:

我有一个分隔文件,其中行有 25 或 26 个字段。 对于所有有 25 个字段的行,我需要在第 13 个字段之后添加一个空行,这样它也将有 26 个字段。

旧:

Z|432651242|987654321|XYZ|Abc|DEFEF||Abc-De-Fg|18|33221|Qwerty|18.06.3213|abc||123|Tepp|11.07.4443|2|||||4433322342344||

新:

Z|432651242|987654321|XYZ|Abc|DEFEF||Abc-De-Fg|18|33221|Qwerty|18.06.3213|abc|||123|Tepp|11.07.4443|2|||||4433322342344||

我设法过滤了需要更改的行:

#!/usr/bin/perl
use strict;
use warnings;

my (@cols,$fieldLength,);
while(<>){
  @cols = split('\|', $_);
  $fieldLength=@cols;
  if ($fieldLength==25){
  print $_;
  }
}

我的想法是替换分隔符“|”在第 13 次出现“||”,但无法做到。我试着用谷歌搜索,但这些例子对我不起作用。

有人可以帮我吗?

我也很欣赏使用 CPAN 的 CSV 模块的解决方案。

【问题讨论】:

  • Text::CSV 会比正则表达式更安全...
  • Text::CSV 是这项工作的正确工具。

标签: regex perl csv delimiter substitution


【解决方案1】:

如果您可以安全地假设分隔符| 永远不会出现在某个字段的数据中,那么您可以使用splitsplice,但Text::CSV 更安全。

#!/usr/bin/perl
use strict;
use warnings;

while (<>)
{
    my @cols = split /[|]/;
    if (scalar(@cols) == 25)
    {
        splice(@cols, 13, 0, '');
        $_ = join('|', @cols);
    }
    print;
}

这似乎产生了您想要的输出。给定输入文件:

Z|432651242|987654321|XYZ|Abc|DEFEF||Abc-De-Fg|18|33221|Qwerty|18.06.3213|abc||123|Tepp|11.07.4443|2|||||4433322342344||
Z|432651242|987654321|XYZ|Abc|DEFEF||Abc-De-Fg|18|33221|Qwerty|18.06.3213|abc|def|123|Tepp|11.07.4443|2|||||4433322342344||

(其中第二行有 def 代替空字段,因此您可以准确看到插入发生的位置),输出为:

Z|432651242|987654321|XYZ|Abc|DEFEF||Abc-De-Fg|18|33221|Qwerty|18.06.3213|abc|||123|Tepp|11.07.4443|2|||||4433322342344||
Z|432651242|987654321|XYZ|Abc|DEFEF||Abc-De-Fg|18|33221|Qwerty|18.06.3213|abc||def|123|Tepp|11.07.4443|2|||||4433322342344||

【讨论】:

  • 谢谢你,成功了。你可能知道,Text::CSV 会是什么样子?
  • 它看起来或多或少像TLP 在他的answer 中显示的代码。
【解决方案2】:

你可以使用Text::CSV来解析行,用splice插入一个空行,然后打印出来。像这样的东西应该可以工作:

use strict;
use warnings;
use Text::CSV;

my $csv = Text::CSV->new({
    sep_char => '|',
    eol      => $/,
});

while (my $row = $csv->getline(*ARGV)) {
    splice(@$row, 12, 0, '') if @$row == 25;
    $csv->print(*STDOUT, $row);
}

【讨论】:

  • 谢谢!只是出于好奇,因为我正在尝试但没有奏效。正则表达式解决方案如何?
  • 这将是不必要的复杂。
  • 似乎是这样,但我首先无法相信仅仅替换这里第 n 次出现的东西会如此复杂。我问是因为我不能在需要使用它的地方使用模块。
  • @TLP:sn-p 有太多错误:构造不起作用(似乎选项必须在 hashref 中),没有检查 or die Text::CSV-&gt;error_diag ();,脚本无法编译: $r 应该是 $row
  • 我将 $r 更改为 $row 但仍然出现错误:Can't use an undefined value as a symbol reference at .\correct.pl 第 11 行。这就是 getline 函数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多