UNIX:模式匹配和排序

时间:2013-04-07 13:53:12

标签: perl bash unix

输入

1   DX
    ADA
4   O1
3   I1
    C1
2   LA
    FTAS
    TT66

预期输出

1   DX
    ADA
2   LA
    FTAS
    TT66
3   I1
    C1
4   O1

命令

  

sort -n输入

我尝试按上面提到的数字排序文件。但它也对空值进行了排序,这搞乱了结构。谢谢您的帮助。

4 个答案:

答案 0 :(得分:6)

那么,您需要将非编号行视为属于编号的行。假设输入中没有出现'%'符号,那么这种解决方案呢?

dtpwmbp:~ pwadas$ cat bzz.txt 
1   DX
    ADA
4   O1
3   I1
    C1
2   LA
    FTAS
    TT66
dtpwmbp:~ pwadas$ cat bzz.txt |perl -0pe 's/\n /%/g'
1   DX%   ADA
4   O1
3   I1%   C1
2   LA%   FTAS%   TT66
dtpwmbp:~ pwadas$ cat bzz.txt |perl -0pe 's/\n /%/g' | sort -n |perl -0pe 's/%/\n /g' 
1   DX
    ADA
2   LA
    FTAS
    TT66
3   I1
    C1
4   O1
dtpwmbp:~ pwadas$ 

在此解决方案中,删除第一个换行符,以保持非编号指定为编号的换行符,然后,在排序后,换行符将返回到其原始位置,因此输出看起来只有编号的换行符。 AFAIR这称为“多线模式”匹配。 我不确定它是否应该转移到superuser.com

答案 1 :(得分:4)

perl -nwe 'if (/^(\d+)/) { $num = $1; } $a[$num] .= $_; 
           END { print for grep defined, @a }' input.txt

只需使用数组根据找到的行号存储行,如果没有找到数字,则使用最后一个数字。然后打印数组。如果您不使用警告开关-w,则不需要使用grep defined,因为警告将在未使用的数组元素上(在这种情况下为0)。

如果行号重复,它会将行附加到前面的条目,这样很方便。它也不需要任何类型的排序,因为数组元素已经排序。

答案 2 :(得分:1)

此输出会跟踪最新的初始数字,并将当前行附加到散列的相应元素上。散列中的数据按键的数字顺序输出。

use strict;
use warnings;

my $n;
my %data;
while (<DATA>) {
  $n = $1 if /^(\d+)/;
  $data{$n} .= $_ if $n;
}

print $_ for map $data{$_}, sort { $a <=> $b } keys %data;

__DATA__
1   DX
    ADA
4   O1
3   I1
    C1
2   LA
    FTAS
    TT66

<强>输出

1   DX
    ADA
2   LA
    FTAS
    TT66
3   I1
    C1
4   O1

<强>更新

您可能更喜欢这种替代方法,即读取整个文件,在每个后跟数字的换行符之后将其拆分,然后按照初始数字的数字顺序对这些记录进行排序。输出与先前的解决方案相同。

use strict;
use warnings;

local $/;
print for sort {
  my ($aa, $bb) = map /^(\d+)/, $a, $b;
  $aa <=> $bb;
} split /(?<=\n)(?=\d)/, <DATA>;

__DATA__
1   DX
    ADA
4   O1
3   I1
    C1
2   LA
    FTAS
    TT66

答案 3 :(得分:0)

我不相信你可以单独使用sort,我会用sed或类似方法处理它,并将其传输到sort然后再回来。