如何使用linux命令进行排序,同时将3行视为1个块并根据每个块的第一行进行排序?
我知道我可以将3行连接成1行然后排序。但是文件太大了,我不想为了排序而生成临时文件。
答案 0 :(得分: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"'
(类似的咒语可以很容易地写在awk
或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
答案 1 :(得分: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