首次匹配后提取匹配行

时间:2017-06-27 18:11:45

标签: perl unix text awk grep

我在命令行中有文本数据,这些数据被分成“记录”,每个都有相同的值(总是1)。在每条记录中,每一行都是一个单独的键和值(不幸的是,这不是在json中)。密钥有时会在记录中重复出现,有时密钥名称是较长密钥的一部分。例如:

Record = 1
  Apple = 1
  Ball = 2
  Car = 3
    RedApple = 4
    Ball = 5
  Dog = 6
  Elf = 7
  Fudge = 8
Record = 1
  Apple = 2
  Ball = 4
  Car = 6
    RedApple = 8
    Ball = 10
  Dog = 12
  Elf = 14
  Fudge = 16
Record = 1
  Apple = 3
  Ball = 6
  Car = 9
    RedApple = 12
    Ball = 15
  Dog = 18
  Elf = 21
  Fudge = 24

每个记录是否有快速获取一组键的行,只返回每个键的第一个结果?

Ex:对于每个记录获取密钥{Apple,Ball,Dog}

将匹配以下行:

Record = 1
  Apple = 1
  Ball = 2
  Dog = 6
Record = 1
  Apple = 2
  Ball = 4
  Dog = 12
...

基本上,规则是在将一行与“记录”匹配后,使用“Apple”,“Ball”和“Dog”获得下一个独特的行(表示精确键匹配的间距)并吐出这些行。

我可以用perl写一些东西,它不会太复杂。我不知道awk,所以不知道这样的事情是否更好。

3 个答案:

答案 0 :(得分:2)

  

每个记录是否有快速获取一组键的行,只返回每个键的第一个结果?

我不相信这实际上是你想要的。我相信您确实希望在第二级标记为AppleBallDog的项目,这意味着

Record = 1
  Apple = 1
  Ball = 2
  Car = 3
    RedApple = 4
    Ball = 5
  Dog = 6
  Elf = 7
  Fudge = 8

Record = 1
  Apple = 1
  Car = 3
    RedApple = 4
    Ball = 5
  Ball = 2
  Dog = 6
  Elf = 7
  Fudge = 8

应该产生

Record = 1
  Apple = 1
  Ball = 2
  Dog = 6

如果是,您可以使用

perl -ne'print if /^(?:\S|[ ]{2}(?:Apple|Ball|Dog)[ ]=)/'

grep -P '^(?:\S|[ ]{2}(?:Apple|Ball|Dog)[ ]=)'

输出:

Record = 1
  Apple = 1
  Ball = 2
  Dog = 6
Record = 1
  Apple = 2
  Ball = 4
  Dog = 12
Record = 1
  Apple = 3
  Ball = 6
  Dog = 18

有关用法,请参阅Specifying file to process to Perl one-liner

答案 1 :(得分:0)

如果这不是你所需要的全部:

$ grep -E '^(Record|  (Apple|Ball|Car))' file
Record = 1
  Apple = 1
  Ball = 2
  Car = 3
Record = 1
  Apple = 2
  Ball = 4
  Car = 6
Record = 1
  Apple = 3
  Ball = 6
  Car = 9

然后编辑您的问题以显示更具真实代表性的示例。现在你已经接受了一个答案,这个答案也是基于猜测你的需要而且可能比必要的更复杂(虽然这可能更简单)。

答案 2 :(得分:-1)

awk救援!

$ awk '/^Record/ {h=$0; a["Apple"]=a["Dog"]=a["Ball"]=0}
       $1 in a   {if(h) {print h; h=""}
                  if(!a[$1]++) print}' file

Record = 1
  Apple = 1
  Ball = 2
  Dog = 6
Record = 1
  Apple = 2
  Ball = 4
  Dog = 12
Record = 1
  Apple = 3
  Ball = 6
  Dog = 18

解释保存标题行并重置计数。对于在必需键中具有第一个字段的行打印标题一次并打印第一次出现该键的行。

如果您只想提取第二级项目,需要将前导空格作为键的一部分(以确定层次结构)。这可以是另一种选择......

$ awk -F' *= *' '/Record/ {h=$0; a["  Apple"]=a["  Dog"]=a["  Ball"]=0} 
                 $1 in a  {if(h) {print h;h=""}; if(!a[$1]++) print}'