输入
1 DX
ADA
4 O1
3 I1
C1
2 LA
FTAS
TT66
预期产出
1 DX
ADA
2 LA
FTAS
TT66
3 I1
C1
4 O1
命令
排序 -n 输入
我尝试如上所述对文件进行数字排序。但它也对空值进行了排序,这弄乱了结构。谢谢您的帮助。
好吧,您需要将未编号的行视为属于编号的行。假设 '%' 符号没有出现在输入中,那么这样的解决方案呢?
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
perl -nwe 'if (/^(\d+)/) { $num = $1; } $a[$num] .= $_;
END { print for grep defined, @a }' input.txt
只需使用数组根据找到的行号存储行,如果没有找到数字,则使用最后一个数字。然后打印数组。如果您不使用警告开关-w
,则不需要使用grep defined
,因为警告将出现在未使用的数组元素上(在这种情况下为 0)。
在重复行号的情况下,它会将行附加到以前的条目中,这很方便。它也不需要任何排序,因为数组元素已经排序。
此输出跟踪最新的初始数字,并将当前行附加到散列的适当元素上。散列中的数据按键的数字顺序输出。
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
我不相信你可以sort
单独使用,我会用sed
或类似的方式处理它,sort
然后再次输入和返回。