2012-11-23 160 views
3

在以下示例中,存在具有进行排序3个元素:形成单个单元如何对行组进行排序?

  1. “[AAA]”和4线(总是4)在其下方。
  2. “[kkk]”和它下面的4行(总是4)组成一个单元。
  3. “[zzz]”和它下面的4行(总是4)组成一个单元。

只有以下这个图案线的基团应该被排序;必须保留“[aaa]”之前和“[zzz]”第4行之后的任何内容。

来自:

This sentence and everything above it should not be sorted. 

[zzz] 
some 
random 
text 
here 
[aaa] 
bla 
blo 
blu 
bli 
[kkk] 
1 
44 
2 
88 

And neither should this one and everything below it. 

到:

This sentence and everything above it should not be sorted. 

[aaa] 
bla 
blo 
blu 
bli 
[kkk] 
1 
44 
2 
88 
[zzz] 
some 
random 
text 
here 

And neither should this one and everything below it. 
+0

多么可怕的例子..你为什么对所有的部分都有相同的值?注意:我会使用'awk'。 –

+0

编辑:现在应该更容易理解。 – octosquidopus

+0

是的,在说明数据前后都是如此。祝你好运。 – shellter

回答

1

也许不是最快的:) [1],但它会做你想要什么,我相信:

for line in $(grep -n '^\[.*\]$' sections.txt | 
       sort -k2 -t: | 
       cut -f1 -d:); do 
    tail -n +$line sections.txt | head -n 5 
done 

这里的更好的一个:

for pos in $(grep -b '^\[.*\]$' sections.txt | 
      sort -k2 -t: | 
      cut -f1 -d:); do 
    tail -c +$((pos+1)) sections.txt | head -n 5 
done 

[1]第一个文件中的行数为O(N^2),因为它必须一直读取每个节的节。第二个可以立即找到正确的字符位置,应该更接近O(N log N)。

[2]这需要你的话,总是有正好在每一节(头加上四以下)五线,因此head -n 5。然而,用一个'['开始的下一行代码来替换它是很容易的,以防万一有必要。


保留的开始和结束需要多一点的工作:

# Find all the sections 
mapfile indices < <(grep -b '^\[.*\]$' sections.txt) 
# Output the prefix 
head -c+${indices[0]%%:*} sections.txt 
# Output sections, as above 
for pos in $(printf %s "${indices[@]}" | 
      sort -k2 -t: | 
      cut -f1 -d:); do 
    tail -c +$((pos+1)) sections.txt | head -n 5 
done 
# Output the suffix 
tail -c+$((1+${indices[-1]%%:*})) sections.txt | tail -n+6 

您可能希望做出来的一个函数,或一个脚本文件,sections.txt改变整个$ 1

+0

它排序,但错误地丢弃页眉和页脚。他们不应该受到程序的影响。 – octosquidopus

+0

一个保持页眉和页脚的方式(另一种方法是首先剥夺他们和它们添加回底。) – rici

1

假设其他线路不包含在他们[

header=`grep -n 'This sentence and everything above it should not be sorted.' sortme.txt | cut -d: -f1` 
footer=`grep -n 'And neither should this one and everything below it.' sortme.txt | cut -d: -f1` 

head -n $header sortme.txt #print header 

head -n $((footer - 1)) sortme.txt | tail -n +$((header + 1)) | tr '\n[' '[\n' | sort | tr '\n[' '[\n' | grep -v '^\[$' #sort lines between header & footer 
#cat sortme.txt | head -n $((footer - 1)) | tail -n +$((header + 1)) | tr '\n[' '[\n' | sort | tr '\n[' '[\n' | grep -v '^\[$' #sort lines between header & footer 

tail -n +$footer sortme.txt #print footer 

供应的目的。

注意,主排序工作仅由4个命令来完成。其他行是预留页眉&页脚。

我还假设,头&第一“[第]”没有其他线之间。

+2

没用使用'cat'发现! –

+0

^^对不起,那是我正在测试。忘了改变它。 – anishsane

0

这可能会为你工作(GNU sed的&排序):

sed -i.bak '/^\[/!b;N;N;N;N;s/\n/UnIqUeStRiNg/g;w sort_file' file 
sort -o sort_file sort_file 
sed -i -e '/^\[/!b;R sort_file' -e 'd' file 
sed -i 's/UnIqUeStRiNg/\n/g' file 

排序文件将在file和原文件中file.bak

这将显示以排序顺序排列的所有以[开头的行和以下4行。

UnIqUeStRiNg可以是不包含换行符的任何唯一字符串,例如, \x00

+0

你忘了页眉和页脚...'这句话,一切上面不应该从您提供的页眉和页脚未排序示例数据sorted.' – anishsane

+0

@anishsane。但是,如果该文件的这些部分可能包括开头的行'[...]'那么sed命令可以更具体,即'/^\ [\(AAA \ | \ KKK \ | ZZZ \)\]!/ B ' – potong