2013-07-29 53 views
2

我有一些数据集(foo),其中barbaz作为部分输出。 baz的部分应排序为输出的顶部。对文本进行排序(unix/shell)

示例输入;

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

在上面的例子中,我想部= foo3 == foo5 =被移动到输出的顶部,并具有列表中部分“名”的子分类,即。

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

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

回答

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; 
    } 
} 
+0

完全作为广告,是一个快速和容易清晰的答案。会和将再次读取A ++。 – Jan

+0

作为一方,我也有“死”空白部分 - 我可以用另一个'elsif'丢弃那些空白部分吗? – Jan

+0

@Jan:那么空白部分会经过第一个if分支,一旦它包含任何内容,即在检查'/ baz /'。你可以在输出时跳过寻找空白部分。 – choroba

2

Lottastuff的解决方案,也叫做脂肪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

我曾经考虑过类似的方法,但最终它看起来太糟糕了*感谢您抽出时间来推荐它,尽管:) – Jan