【问题标题】:Sed match between matching curling brackets匹配的花括号之间的 sed 匹配
【发布时间】:2019-11-06 20:50:26
【问题描述】:

我有以下文件:

Items{
 Item{
    car "blue"
    tire 4
  }
 Item{
    car "yellow"
    tire 0
 }
}
Orders{
 Order{
    ID 123
    Cost 123
 }
 Order{
    ID 231
    Cost 2
 }
}

我需要 in sed 来匹配 Items{ 和该组的最后一个匹配 } 之间的所有内容......现在我可以这样做:

sed -n /Items/,/^\}/p

问题是,文件对空间不敏感,子类别的其他括号也可以在行首......知道如何普遍匹配它吗?它需要在 sed 中,因为稍后我需要那个“匹配”来精确定位编辑......

编辑了示例文件

【问题讨论】:

  • 发布预期结果
  • 你不能在/Items/,/Orders/ 范围内匹配然后只删除最后一行吗?
  • @RomanPerekhrest 预期结果是:Items{ Item{ car​​ "blue" 轮胎 4 } Item{ car​​ "yellow" 轮胎 0 }
  • @choroba 不幸的是,下一个类别的名称一直不一样,它的文件超级凌乱,现在翻遍了 20 个,每个在格式上都略有不同,主要类别我m after 可以是文档中的任何位置
  • 是否应该关闭每个项目?在“订单”开始之前,“项目”不会关闭。你能澄清一下这种格式的规则吗?

标签: regex sed


【解决方案1】:

解决问题的选择很少

  1. 将文件转换为标准格式(XML、JSON),并使用标准工具(xml、xsltproc 或 jq)解析文件。
  2. Pretty-print 文件,然后使用缩进标识块末端。
  3. 编写自定义分词器,计算开/关大括号。

选择#2,使用perl 构建漂亮的打印格式化程序。可以使用任何工具(sed、awk、...)进行提取。

perl pp-data.pl filename.txt | sed -n 'sed -n '/^Items/,/^}/p'
#! /usr/bin/perl
# pp-data.pl
use strict ;
my $d = eval { local $/ ; <> } ;
my $l = 0 ;
my $n = 0 ;
while ( $d =~ /({|}|\w+|"[^"]*")/g ) {
        my $w = $1 ;

        $l-- if $w eq '}' ;

        print $n ? " " : (" " x ($l * 2)), $w ;
        $n++ ;

        if ( $w eq "{" ) {
                $l++ ;
                $n = 0 ;
        } elsif ( $w eq "}" ) {
                $n = 0 ;
        } elsif ( $n == 2 ) {
                $n = 0 ;
        } ;
        print "\n" unless $n ;
} ;
1;

对于答案中的输入,解析后的输出将如下所示:

Items {
  Item {
    car "blue"
    tire 4
  }
  Item {
    car "yellow"
    tire 0
  }
}
Orders {
  Order {
    ID 123
    Cost 123
  }
  Order {
    ID 231
    Cost 2
  }
}

【讨论】:

  • 谢谢,重新格式化文件可能是最好的办法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-24
  • 1970-01-01
  • 1970-01-01
  • 2012-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多