我有一些数据集(foo
),其中bar
和baz
作为部分输出。带baz
的部分应排序到输出的顶部。
示例输入;
= foo4 =
bar
(..)
barN
= foo1 =
bar
(..)
barN
= foo5 =
bar
(..)
barN
baz
= foo2 =
bar
(..)
barN
= foo3 =
bar
(..)
barN
baz
在上面的示例中,我希望将= foo3 =
和= foo5 =
部分移动到输出的顶部,并将列表按“name”部分进行子排序,即。
= foo3 =
= foo5 =
= foo1 =
= foo2 =
= foo4 =
但该部分的内容完好无损。
答案 0 :(得分:2)
Lottastuff解决方案,a.k.a。, fat-oneliner :
awk '/^=/{print ""} {printf "%s\t", $0}' input.txt | \
awk '{print ($NF != "baz")"\t"$0}' | sort -n | cut -f 2- | \
tr '\t' '\n' | sed -e '/^$/d'
最初的转变过于挑剔。应该有一些工具能够粘贴行直到分隔符(:
答案 1 :(得分:1)
Perl解决方案。它使用部分的散列,键是部分的名称,该值包含部分开始的文件中的位置以及是否存在baz
的信息。将文件读入哈希后,将对键进行排序并打印内容,并在记住的文件中移动。
#!/usr/bin/perl
use warnings;
use strict;
my $file = shift;
my $start = qr/^= (.*) =$/;
open my $FH, '<', $file or die $!;
my %sections;
my $current_section;
while (<$FH>) {
if (/$start/) {
$current_section = $1;
$sections{$current_section}{begin} = tell $FH;
} elsif (/baz/) {
$sections{$current_section}{baz} = 1;
}
}
for my $section (map substr( $_, 1),
sort map { ($sections{$_}{baz} ? '0' : '1') . $_ }
keys %sections) {
seek $FH, $sections{$section}{begin}, 0;
print "= $section =\n";
while (<$FH>) {
last if /$start/;
print;
}
}