按正则表达式排序

按正则表达式排序

我有一组 POSIX 正则表达式*

^BEGIN:VCARD\r$
^VERSION[^A-Z]
^FN[^A-Z]
^N[^A-Z]
^NICKNAME[^A-Z]
^EMAIL[^A-Z]
^X-\([A-Z-]*\)
^TEL[^A-Z]
^ADR[^A-Z]
^ORG[^A-Z]
^TITLE[^A-Z]
^BDAY[^A-Z]
^URL[^A-Z]
^ROLE[^A-Z]
^NOTE[^A-Z]
^END:VCARD\r$

以及一个文件,其中每行都与正则表达式之一匹配:

BEGIN:VCARD
VERSION:3.0
N:Doe;Jane;;Ms;
URL:http://janedoe.com/
EMAIL:[email protected]
EMAIL:[email protected]
BDAY:1970-01-01
X-JABBER:[email protected]
X-ICQ:1234567890
END:VCARD

我想根据以下内容对这些行进行排序

  1. 正则表达式匹配的行号(以便以 FN 开头的行位于以 N 开头的行之前),
  2. 匹配组(以便 X-ABC 位于 X-DEF 之前)

理想情况下,不应对行的其他部分进行排序(因此应保留以 EMAIL 开头的行序列)。因此,预期结果应该是:

BEGIN:VCARD
VERSION:3.0
N:Doe;Jane;;Ms;
EMAIL:[email protected]
EMAIL:[email protected]
X-ICQ:1234567890
X-JABBER:[email protected]
BDAY:1970-01-01
URL:http://janedoe.com/
END:VCARD

有现有的工具可以做到这一点吗?

编辑:实施结果基于拉尔斯·罗尔巴赫的回答

* 这是 Gmail 联系人导出文件中 vCard 属性的序列。

答案1

通常的sort命令不提供指定特定“字典”的包含方式,虽然该grep命令允许您提供正则表达式文件,但它不会更改输出的顺序。但是您可以将两者放在一个简单的foreach循环中 - 这是一个在 bash shell 中运行的示例:

for i in `cat fileofregexp`; do grep "$i" myinputfile; done

这将从正则表达式文件中逐一获取每个正则表达式行,并输出输入文件中的任何匹配项,因此生成的输出将按正则表达式顺序排序。请注意,输入文件中完全不匹配的任何行都不会出现在输出中。

附录:根据要求,这是一个使用循环的版本while

while IFS= read -r i; do grep "$i" myinputfile; done  < fileofregexp

答案2

这并不完全是您的框架方式,但考虑到您的实际目的,抓住冒号之前的部分并按其排序会更简单。下面是一个 Perl 脚本,它将来自单独的排序键的行累积到单独的数组条目中,并在到达末尾时刷新 vcard。

#!/usr/bin/perl -n
BEGIN {
    @headers = qw(BEGIN VERSION FN N NICKNAME EMAIL X- TEL ADR ORG TITLE BDAY URL ROLE NOTE END);
    for $h (@headers) { $data{$h} = ""; }
}
if (/^([^:]+):/) {
    $data{exists $data{$1} ? $1 : "X-"} .= $_;
    if ($1 eq 'END') {
        for $h (@headers) { print $data{$h}; $data{$h} = ""; }
    }
} else {
    print;
}

如果您确实想要完整的正则表达式灵活性,请迭代正则表达式,而不是在哈希中查找键。

#!/usr/bin/perl -n
BEGIN {
    @regexps = qw(^BEGIN:VCARD\r$ ^VERSION[^A-Z] ^FN[^A-Z] ^N[^A-Z] ... ^END:VCARD\r$);
    for $r (@regexps) { $data{$r} = ""; }
}
for $r (@regexps) {
    next unless $_ =~ $r;
    $data{$r} .= $_;
    last;
}
if ($_ =~ $regexps[@regexps-1]) {
    for $r (@regexps) { print "++", $data{$r}; $data{$r} = ""; }
}

相关内容