1

How to sort with linux command, while treat 3 lines as 1 block and sort based on the first line of each block?

I know I can concat 3 lines into 1 line and then sort. But the file is simply too big, and I don't wan't to generate a temp file just for sorting.

4

2 回答 2

3

sort对文本文件的行进行排序,其中一条记录始终由换行符分隔。作为一个例外,它也支持\0作为记录分隔符,但无法更改记录分隔方式的逻辑

您可以利用上述异常来实现decorate-sort-undecorate模式,如下所示:

chunk | sort -z -t'
' -k1 | unchunk

chunk将每三行组合成line1\0line2\0line3\n,以允许sort -z将三行块作为单个记录获取,并按记录-t'\n' -k1中的第一个字段排序。unchunk只是全部变\0\n.

用 Perl 表示,chunk看起来像这样:

perl -pe 'chomp;$_.=($.%3)?"\n":"\0"'

(类似的咒语可以很容易地用awkor编写sed,而 C 版本不会更长。)

unchunk不超过tr '\0' '\n'。因此完整的排序是:

perl -pe 'chomp;$_.=($.%3)?"\n":"\0"' | sort -z -t'
' -k1 | tr '\0' '\n'

给定输入文件

b
2nd b line
bla 3rd b line
a
some a line
other a line
x
first x line
other x line

...上述管道产生:

a
some a line
other a line
b
2nd b line
bla 3rd b line
x
first x line
other x line
于 2013-04-19T23:21:48.757 回答
0

下面的单行代码在 bash 中完成了这项工作。它只是将数据读入一个由三行三行组成的 perl 数组,在第一行排序,然后打印所有内容。

您可以轻松地将排序谓词更改为例如按数字排序(<=>用于此)或以您喜欢的任何其他方式。这个使用字典顺序。

要使其在 Windows 中工作,只需切换引号:在外部使用“”,在内部使用 ''。

$ perl -e 'while(<>){push@a,[$_,scalar<>,scalar<>]}for(sort{$a->[0]cmp$b->[0]}@a){print join"",@$_}' < foo.txt

这假设输入在foo.txt.

实际上我刚刚意识到你可以只连接而不是使用内部数组。结果更短!

$ perl -e 'while(<>){push@a,$_.scalar<>.scalar<>}for(sort @a){print}' < foo.txt
于 2013-04-19T23:36:17.230 回答