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 '#'将其用作记录分隔符。它认为整个文件是一个记录。
一种解决方案是首先将块内的换行符更改为您选择的未使用字符(在下面的示例中为“|”),对结果进行排序并将所选分隔符更改回原始换行符:
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)
perl -0ne 'print sort /(#+[^#]*)/g' file.txt
Run Code Online (Sandbox Code Playgroud)
perl -0 吞掉整个文件/(....)/g 匹配并提取记录print sort ... 排序并打印它们