Sed - 地址范围内的条件分支

时间:2013-03-20 01:59:20

标签: parsing loops sed branch labels

我需要从一些原始文本数据格式化批量条目文件。我能够使用Sed来实现我的解决方案的大部分,这是/首选,但不是绝对必需的(我只想坚持使用这一个工具)。当我让分支疯狂试图解析[更大量]以下输入时,问题变得清晰了:

---- Start Product ----
PartNumber>> 123457
Size04_Req>> 2 
Size02_Req>> 1 
PartColor>> Natural
PartDescription>> Guys Tee 
---- End Product ----
---- Start Product ----
PartNumber>> TPIOO9205
Size05_Req>> 1 
PartColor>> Natural
PartDescription>> Black Hoodie


---- End Product ----


###...with the objective of achieving the following output:


---- Start Product ---
PartNumber>> 123457
Size01_Req>> 0 
Size03_Req>> 0 
Size05_Req>> 0 
Size06_Req>> 0
Size04_Req>> 2 
Size02_Req>> 1 
PartColor>> Natural
PartDescription>> Guys Tee
---- End Product ----
---- Start Product ----
PartNumber>> TPIOO9205
Size01_Req>> 0 
Size02_Req>> 0 
Size03_Req>> 0 
Size04_Req>> 0 
Size06_Req>> 0
Size05_Req>> 1 
PartColor>> Natural
PartDescription>> Black Hoodie
---- End Product ----

我相信这就像在地址范围内工作一样简单 / ---- \ Start \ Product \ ---- /,/ ---- \ End \ Product \ ---- / 并且做了一些优雅的分支和标签工作,但我的倾向显然是为了这个逻辑而跳上Awk或其他东西 - 因为我疯了 - 而且用其他工具也许会更容易为达到这个。然而,坚持我最初与Sed的关系,并且因为我想在任何一天学习一个新的Sed技巧,这怎么可能呢?请注意,逻辑是插入 SizeXX_Req>> 0 对于未考虑的大小01-06,并且顺序并不重要,这就是为什么我认为Sed甚至可以完成最后一小部分半熟练的工作。每个“开始/结束产品”部分之间始终至少有一个 SizeXX_Req 行。任何Sed(i)大师都可以快速完成这项工作吗?我是不是只是从最近写的那些正则表达式中找出来并且错过了一个简单的解决方法? 前进。用另一种rando语言向我展示,甚至没有解释你是如何(或为什么)做的,我也是这样。提前谢谢,偷看。

1 个答案:

答案 0 :(得分:0)

使用sed执行此操作对我来说似乎不可能,因为您需要一个计数器和某种后向引用。也许我错了,无论如何,使用Perl:

use warnings;
use strict;

my (%sizes, %part);
while(<>) {
  if (/^---- End Product ----/) {
    print "---- Start Product ----\n";
    print "PartNumber>> $part{Number}\n";
    for my $size (map { sprintf "%02d", $_ } 1..6) {
      if (not defined $sizes{$size}) {
        print "<b>Size${size}_Req>> 0</b>\n";
      }   
    }   
    for my $size (keys %sizes) {
      print "Size${size}_Req>> $sizes{$size}\n";
    }   
    print "Part$_>> $part{$_}\n" for ("Color", "Description");
    print "---- End Product ----\n";
    %sizes = (); 
    %part  = (); 
  }
  $sizes{$1} = $2 if (/^Size(\d+)_Req>>\s*(\d+)/);
  $part{$1} = $2 if (/^Part(\w+)>> (.*)/);
}

使用

perl script.pl input

<强>输出

---- Start Product ----
PartNumber>> 123457
<b>Size01_Req>> 0</b>
<b>Size03_Req>> 0</b>
<b>Size05_Req>> 0</b>
<b>Size06_Req>> 0</b>
Size04_Req>> 2
Size02_Req>> 1
PartColor>> Natural
PartDescription>> Guys Tee 
---- End Product ----
---- Start Product ----
PartNumber>> TPIOO9205
<b>Size01_Req>> 0</b>
<b>Size02_Req>> 0</b>
<b>Size03_Req>> 0</b>
<b>Size04_Req>> 0</b>
<b>Size06_Req>> 0</b>
Size05_Req>> 1
PartColor>> Natural
PartDescription>> Black Hoodie
---- End Product ----