2

我有一些数据集 ( foo),其中barbaz作为部分的输出。部分baz应该被排序到输出的顶部。

示例输入;

= foo4 =
bar
(..)
barN
= foo1 =
bar
(..)
barN
= foo5 =
bar
(..)
barN
baz
= foo2 =
bar
(..)
barN
= foo3 =
bar
(..)
barN
baz

在上面的示例中,我希望将部分= foo3 == foo5 =移动到输出的顶部,并让列表按部分“名称”进行子排序,即。

= foo3 =
= foo5 =
= foo1 =
= foo2 =
= foo4 =

但该部分的内容完好无损。

4

2 回答 2

2

Lottastuff 解决方案,又名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'

最初的转变太挑剔了。应该有一些工具能够粘贴行直到分隔符(:

于 2013-07-29T23:48:21.183 回答
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;
    }
}
于 2013-07-29T12:24:30.603 回答