【问题标题】:How to split lines in one part of a text file differently from another? - Perl如何在文本文件的一部分中以不同于另一部分的方式分割行? - Perl
【发布时间】:2019-03-14 20:54:58
【问题描述】:

我对编码很陌生。

我有一个文本文件中的数据,格式如下:

#
PROPERTY_A: TEXT1
PROPERTY_B: UNIT1
#
PROPERTY_A: TEXT2
PROPERTY_B: UNIT2
#
#
1 2
3 4

我想像这样将它输出为表格:

TEXT1 TEXT2
UNIT1 UNIT2
1     2
3     4

我了解如何将文本文件读入行数组,然后如何使用 split() 将每一行解析为字符串数组。我想将数据写入一个表格,其中属性作为每列的标题,所以我需要使用“:”进行拆分,直到我读取 2 行带有哈希的连续行,然后更改为使用“”进行拆分。

使用此代码给了我一个无限循环,即使两个单独的拆分都可以正常工作,它也不会返回任何值。

my $dataAsText = SomeFunction->Run($imputDocument);
for (my $ln = 0; < $dataAsText->Lines->Count; ++$ln;)
my $line = $dataAsText->Lines($ln)
do {
   my @words = split ($line, ‘: ‘, 2);
   # then pass @words[1] to the first or second row of each column
} until ($line eq ‘#’ && $line + 1 eq ‘#’);
   my @words = split ($line, ‘ ‘);
   # then pass each @words values to its corresponding column
}

我将如何编写一段代码来检查 2 个带有哈希符号的连续行,然后在将它们发送到数组之前更改这些行的拆分方式?

只是为了澄清最终的数据文档可能有数十万行要阅读,这是一个示例结构。

【问题讨论】:

  • 我不明白你想要什么输出——你能用你显示的文件中的数据来显示吗?此外,显示的代码本身并没有多大意义——你能展示更多,特别是你如何阅读和迭代行吗?
  • 感谢您的澄清。但是:当您说“使用此代码给我”时,它似乎指的是您显示的代码,这是不可能的,因为这与正确的 Perl 相去甚远,并且无法编译(在许多情况下)。

标签: perl


【解决方案1】:

你可以试试命令行 Perl

perl -F: -ane ' if(not /^\d+/) { $x.=$F[1] if not /^#/ } else { $y.=$_ } 
    END { $x=~s/\s*(\S+)\s*(\S+)\s*(\S+)\s*(\S+)/$1 $3\n$2 $4/gs; print $x,$y }' file

使用您给定的输入:

$ cat marPar.txt
#
PROPERTY_A: TEXT1
PROPERTY_B: UNIT1
#
PROPERTY_A: TEXT2
PROPERTY_B: UNIT2
#
#
1 2
3 4

$ perl -F: -ane ' if(not /^\d+/) { $x.=$F[1] if not /^#/ } else { $y.=$_ } 
      END { $x=~s/\s*(\S+)\s*(\S+)\s*(\S+)\s*(\S+)/$1 $3\n$2 $4/gs; print $x,$y }' marPar.txt
TEXT1 TEXT2
UNIT1 UNIT2
1 2
3 4

$

【讨论】:

  • @zdim.. 谢谢.. 刚刚更新.. 我还有一个问题.. 如何打印 $' ,单行解决方案中正则表达式匹配后的正确部分..跨度>
  • 哇,不错的……不知道。除了使用它的"english" nameperl -MEnglish -wE'$_=q(abc); /./; say $POSTMATCH'。在早于 (..X?) 的 Perls 中,这会导致性能损失,而 ${^POSTMATCH} 也会这样做而不会造成损失。但我认为无论如何都不会受到惩罚。 (使用" 作为脚本分隔符要么太乱要么不起作用)
【解决方案2】:

应该这样做。您要做的是检测以哈希开头的行并对其进行计数;当您连续看到两个时,交换您用来进行拆分的模式。

{
  # Inside a block so only the sub here can see them.
  my $double_hash_seen;
  my $splitter = qr/:/;   # First split pattern
  my $last_was_hash;

  sub split_appropriately {
    my($line) = @_;
    if (/^#/) {
      if ($last_was_hash) {
        # Double hash, switch modes.
        $splitter = qr/ /;  # Second split pattern
        return;             # We don't split hash lines
      }
      # Last was not a hash, but this was.
      $last_was_hash = 1;  # One hash seen.
      return;              # Don't split the hash line
    }
    # This isn't a hash. Turn off "hash seen" and split
    # with appropriate current pattern.
    $last_was_hash = 0;
    split $splitter, $line;  # Will stay switched once it changes
  }
}

while(<DATA>) {
  my($first, $second) = split_appropriately($_);
  next unless defined $first;
  print "Part 1: $first\n";
  print "Part 2: $second\n";
}
__DATA__
#
PROPERTY_A: TEXT1
PROPERTY_B: UNIT1
#
PROPERTY_A: TEXT2
PROPERTY_B: UNIT2
#
#
1 2
3 4

【讨论】:

    猜你喜欢
    • 2020-09-18
    • 1970-01-01
    • 2013-08-21
    • 2023-03-18
    • 2023-03-14
    • 1970-01-01
    • 2020-12-14
    • 2016-06-02
    • 1970-01-01
    相关资源
    最近更新 更多