将多行文本文件作为一行进行排序

Ari*_*yan 14 linux text-processing sort

我有一个这种格式的文本文件:

####################################
KEY2
VAL21
VAL22
VAL23
VAL24
####################################
KEY1
VAL11
VAL12
VAL13
VAL14
####################################
KEY3
VAL31
VAL32
VAL33
VAL34
Run Code Online (Sandbox Code Playgroud)

我想按KEY行对此文件进行排序,并将接下来的 4 行保留在结果中,因此排序结果应为:

####################################
KEY1
VAL11
VAL12
VAL13
VAL14
####################################
KEY2
VAL21
VAL22
VAL23
VAL24
####################################
KEY3
VAL31
VAL32
VAL33
VAL34
Run Code Online (Sandbox Code Playgroud)

有没有办法做到这一点 ?

Pet*_*des 13

msort(1)旨在能够对具有多行记录的文件进行排序。它有一个可选的 gui,以及一个普通且可供人类使用的命令行版本。(至少,喜欢仔细阅读手册并寻找示例的人类......)

AFAICT,您不能对记录使用任意模式,因此除非您的记录是固定大小的(以字节为单位,而不是字符或行)。 对于由空行分隔的行块的记录,msort确实有一个-b选项。

您可以将输入转换为-b易于使用的格式,方法是在每个之前###...(第一个除外)放置一个空行。

默认情况下,它会在 stderr 上打印统计信息,因此至少很容易判断它何时没有排序,因为它认为整个输入是单个记录。


msort适用于您的数据。sed命令在#+除第 1 行之外的每一行前添加一个换行符。 -w对整个记录进行排序(按字典顺序)。可以选择将记录的哪一部分用作密钥,但我不需要它们。

我也没有去除多余的换行符。

$ sed '2,$ s/^#\+/\n&/' unsorted.records | msort -b -w 2>/dev/null 
####################################
KEY1
VAL11
VAL12
VAL13
VAL14

####################################
KEY2
VAL21
VAL22
VAL23
VAL24

####################################
KEY3
VAL31
VAL32
VAL33
VAL34
Run Code Online (Sandbox Code Playgroud)

我没有运气-r '#'将其用作记录分隔符。它认为整个文件是一个记录。


xhi*_*nne 9

一种解决方案是首先将块内的换行符更改为您选择的未使用字符(在下面的示例中为“|”),对结果进行排序并将所选分隔符更改回原始换行符:

sed -e 'N; N; N; N; N; s/\n/|/g' file.txt \
| sort -k2,2 -t\| \
| sed 's/|/\n/g'
Run Code Online (Sandbox Code Playgroud)


JJo*_*oao 5

perl -0ne 'print sort /(#+[^#]*)/g' file.txt
Run Code Online (Sandbox Code Playgroud)
  • perl -0 吞掉整个文件
  • /(....)/g 匹配并提取记录
  • print sort ... 排序并打印它们