在另一行中找到匹配后跟另一个匹配并对输出进行排序

时间:2014-05-06 00:27:34

标签: regex perl sed grep xargs

我有一个文件格式如下:

First Name : aa
#some noninteresting info
...
#some noninteresting info
Last Name : tt
First Name : cc
#some noninteresting info
...
#some noninteresting info
Last Name : ss

我需要生成另一个只有名字和姓氏的文件,并根据姓氏排序:

First Name : cc
Last Name : ss
First Name : aa
Last Name : tt

我尝试了以下内容:

grep "Last Name :" | sort 

但这只是我想要的一半。如何将First Name添加到与姓氏相对应的名称并根据姓氏保存它们?

3 个答案:

答案 0 :(得分:2)

如果你有GNU sed,那么你可以将grep的输出传递给它。

grep -E '(First|Last) Name' file | sed 'N;s/\n/ /' | sort -k8 | sed 's/Last/\nLast/'
First Name : cc
Last Name : ss
First Name : aa
Last Name : tt
  • grep -E '(First|Last) Name' file将使用名字和姓氏点击
  • sed 'N;s/\n/ /'会将姓氏附加到名字
  • sort -k8将对第8个字段进行排序,即Last Name值
  • sed 's/Last/\nLast/'会将它们放在不同的行上

如果您没有GNU sed,那么您的另一个选择就是使用xargs

grep -E '(First|Last) Name' file | xargs -n8 | sort -k8 | xargs -n4
First Name : cc
Last Name : ss
First Name : aa
Last Name : tt

注意:这假设您的数据包含每个条目的名字和姓氏。 xargs解决方案假定您的名字没有中间名

答案 1 :(得分:0)

您可以轻松使用正则表达式来完成过滤:

grep -E "(Last|First) Name :"

但要按顺序排列""显示名字时的姓氏,您需要在排序之前进行更多处理。也许您可以查看sedawk来帮助完成该部分。

您可以这样做的方法是将正则表达式更改为包含名字和姓氏的单个匹配,将姓氏附加到匹配的开头,对其进行排序,然后删除最后一个名字....复杂,但是一种可行的方法。

答案 2 :(得分:0)

使用perl one-liner

perl -e 'print sort {@l = map /([^:]*)\Z/, $a, $b; $l[0] cmp $l[1]} split /(?=^First)/m, join q{}, grep /Name :/, <>' file.txt

打破它。从下到上阅读。

perl -e '
     print                                                   # Print results
     sort {@l = map /([^:]*)\Z/, $a, $b; $l[0] cmp $l[1]}    # Sort based off last phrase after a :
     split /(?=^First)/m,                                    # Split on lines beginning with First
     join q{},                                               # Join all lines together
     grep /Name :/,                                          # Filter all those not containing Name :
     <>                                                      # Slurp all the lines
   ' file.txt