对文件的一部分进行排序

对文件的一部分进行排序

是否可以在大文件中的两个字符串之间进行排序?

例如当前文件如下:

    0cf  Front Brake
    0d0  Rear Brake
    0ce  Handle Bars
HUT 03  VR Controls
    009  Vest
    001  Belt
    002  Body Suit
    020  Stereo Enable
    003  Flexor
    007  Hand Tracker
    004  Glove
    006  Head Mounted Display
    008  Oculometer
    00a  Animatronic Device
    000  Unidentified
    021  Display Enable
    005  Head Tracker
HUT 04  Sport Controls
    000  Unidentified
    002  Golf Club
    001  Baseball Bat

所需的输出如下:

    0ce  Handle Bars
    0cf  Front Brake
    0d0  Rear Brake
HUT 03  VR Controls
    000  Unidentified
    001  Belt
    002  Body Suit
    003  Flexor
    004  Glove
    005  Head Tracker
    006  Head Mounted Display
    007  Hand Tracker
    008  Oculometer
    009  Vest
    00a  Animatronic Device
    020  Stereo Enable
    021  Display Enable
HUT 04  Sport Controls
    000  Unidentified
    001  Baseball Bat
    002  Golf Club

在这里,部分HUT 03 VR 控制HUT 04 运动控制已整理出来。

在给定文件中,节标题以非空格字符开头,而节内容始终以空格或制表符开头。由于该文件有 100 多个部分,因此在脚本/命令中硬编码部分名称是不可行的

答案1

在Python中:

#!/usr/bin/python3

with open("file.txt", "r") as ins:
    lines = []
    for line in ins:
        if line.startswith((" ", "\t")):
            lines.append(line)
        else:
            lines.sort()
            print(*lines, end = "", sep = "")
            print(line, end = "")
            lines = []
    lines.sort()
    print(*lines, end = "", sep = "")

这会对所有部分(单独)进行排序,而不仅仅是两条特定行之间的部分。

答案2

$ awk 'BEGIN { OFS="\t"; s=0 } /^[^[:blank:]]/ { print ++s "\b", $0; next } { print s, $0 }' file | sort -n | cut -f 2-
    0ce  Handle Bars
    0cf  Front Brake
    0d0  Rear Brake
HUT 03  VR Controls
    000  Unidentified
    001  Belt
    002  Body Suit
    003  Flexor
    004  Glove
    005  Head Tracker
    006  Head Mounted Display
    007  Hand Tracker
    008  Oculometer
    009  Vest
    00a  Animatronic Device
    020  Stereo Enable
    021  Display Enable
HUT 04  Sport Controls
    000  Unidentified
    001  Baseball Bat
    002  Golf Club

这用于awk在与该行所在部分相对应的每行前面添加一个数字(和一个制表符分隔符)。对于节标题,我们添加一个数字,后跟一个退格字符(只是因为退格键在制表符之前排序)。然后,我们只需对这些数字的结果数据进行排序,然后删除它们和添加的制表符分隔符。

通过在行开头查找非空白字符来检测节标题。

答案3

为了好玩,这里有一种使用以下方法对单个部分进行排序的方法ex

ex file <<%
/HUT
+1,/HUT/-1!sort
w file.sorted
q
%

答案4

对于此类任务,我经常发现编写脚本很乏味。如果只需要完成一次并且可能只需要完成几个文件,那么如果您打开文件vim并键入:

  • GoFAKE SECTION<ESC>:在最后添加一个假部分,并确保它位于行的开头(您可能已经cindentautoindent启用)。这对于对最后一部分进行排序也是必需的。
  • gg: 返回到文件的开头,然后文件从一个部分开始,向下一行j
  • qq:开始录制宏来注册q
  • v:开始选择
  • /^\S\+<Enter>:搜索下一节的开头
  • k: 向上一行
  • :!sort<Enter: 对部分进行排序
  • nj:转到下一节的第一个元素
  • q:停止录制宏
  • @q: 重复宏
  • 100@@:重复宏几次(直到没有剩余部分)
  • dd:删除文件的最后一行(FAKE SECTION

您可能想:set lazyredraw加快宏执行速度。

相关内容