对行块进行排序


12

我有一个包含4n行的文件。这是其中的摘录,包含8行

6115 8.88443
6116 6.61875
6118 16.5949
6117 19.4129
6116 6.619 
6117 16.5979 
6118 19.4111
6115 8.88433  

我想要做的是对一个块进行排序,其中每个块均基于第一列包含4行。摘录的输出应如下所示。

6115 8.88443
6116 6.61875
6117 19.4129
6118 16.5949
6115 8.88433 
6116 6.619 
6117 16.5979 
6118 19.4111 

Answers:


16

一种选择是使用每N行添加一个初始序列号前缀(在您的情况下为N = 4)。然后将前缀作为主要排序列输入sort

N = 4的示例:

awk '{print int((NR-1)/4), $0}' file.txt | sort -n -k1,1 -k2,2 | cut -f2- -d' '

7

如果这是一次性的,并且您不想学习python,perl或awk,则可以使用basic splitsort命令。

首先使用以下-l 选项将文件分成4行:

split -a 6 -l 4 input_file my_prefix_
for fn in my_prefix_*; do
    sort -n -o $fn $fn
done
cat my_prefix_* > output_file
rm my_prefix_*

sort -n种类通过的第一列(999 1234之前)的数值。 -a 6应该照顾一个26 ^ 6 * 4行的文件。my_prefix_对于您使用的目录应该是唯一的。


3

您可以使用Perl做到这一点:

perl -nle '
   push @a,$_;
   unless($. % 4){
       print join "\n",sort {$a <=> $b} @a; # Sort @a, and print its contents
       @a = (); # Empty @a to start a new block
   }
' your_file

如何运作

  • -n->为每个输入行运行代码(并将当前行放入$_
  • -l ->在任何输出的末尾添加换行符 print
  • -e ->执行以下字符串作为Perl代码
  • 每行都附加到数组@a
  • $.保持当前行号,除非该数字不等于零模4,否则我们继续工作。如果它全等零模4,我们已经达到了,其数量是4(块的结尾)的倍数的线,在这种情况下,我们的排序中的条目@a数字升序和打印排序后的数组中的条目通过换行符连接到标准输出。

2

使用类似Bourne的外壳,

while read a ; do                                           # Try reading a line.
    read b ; read c ; read d                                # OK, read 3 more.
    printf '%s\n%s\n%s\n%s\n' "$a" "$b" "$c" "$d" | sort -n # Sort them.
done < data

2

以下是一些“纯” awk解决方案:

如果索引始终是与示例数据相同的递增整数序列(6115-6119),则可以使用算法“快捷方式”:

awk '{a[$1]=$0} !(NR%4){for(i=6115;i<6119;print a[i++]);}'

这确实

  • 将所有行添加到数组a,分布在索引位置6115-6119
  • 在第4行(!(NR%4))上,循环遍历数组内容,以所需顺序打印。

如果数字索引始终是四个相同的索引,而不是递增的整数序列,则必须进行排序:

awk '{a[$1]=$0} !(NR%4){asort(a,b); for(i=1;i<5;print b[i++]);}'

注意:这是与GNU awk一起使用的,其他人可能不支持asort


如果每个四分之一的块都有不同的数字ID:

awk '{a[$1]=$0} !(NR%4){asort(a); for(i=1;i<5;print a[i++]); delete a}'

注意:@Gilles self-answer(+2)的delete TIL 尚不支持POSIX,但普遍支持


正确使用以下版本的版本delete

awk '{a[$1]=$0} !(NR%4){asort(a); for(i=1;i<5;delete a[i++]){print a[i]}}'

没有删除的版本,使用了更多的内存和尺寸:

awk '{a[n][$1]=$0} !(NR%4){asort(a[n]); for(i=1;i<5;print a[n][i++]); n++}

1

您可以使用R获得干净的解决方案。如果上表在名为“ table.txt”的文件中,请执行以下步骤。所需的结果将在文件“ tableout.txt”中。

> x = read.table("table.txt", col.names=c("a", "b"))
> x
     a        b
1 6115  8.88443
2 6116  6.61875
3 6118 16.59490
4 6117 19.41290
5 6116  6.61900
6 6117 16.59790
7 6118 19.41110
8 6115  8.88433
> x["index"] = c(rep(1, 4), rep(2, 4))
> x
     a        b index
1 6115  8.88443     1
2 6116  6.61875     1
3 6118 16.59490     1
4 6117 19.41290     1
5 6116  6.61900     2
6 6117 16.59790     2
7 6118 19.41110     2
8 6115  8.88433     2     
> xord = x[with(x, order(index, a)), ]
> xord
     a        b index
1 6115  8.88443     1
2 6116  6.61875     1
4 6117 19.41290     1
3 6118 16.59490     1
8 6115  8.88433     2
5 6116  6.61900     2
6 6117 16.59790     2
7 6118 19.41110     2
> write.table(xord[,1:2], "tableout.txt", row.names=FALSE, col.names=FALSE)

另请参见如何按R中的列对数据框进行排序

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.