是否可以在大文件中的两个字符串之间进行排序?
例如当前文件如下:
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>
:在最后添加一个假部分,并确保它位于行的开头(您可能已经cindent
或autoindent
启用)。这对于对最后一部分进行排序也是必需的。gg
: 返回到文件的开头,然后文件从一个部分开始,向下一行j
qq
:开始录制宏来注册qv
:开始选择/^\S\+<Enter>
:搜索下一节的开头k
: 向上一行:!sort<Enter
: 对部分进行排序nj
:转到下一节的第一个元素q
:停止录制宏@q
: 重复宏100@@
:重复宏几次(直到没有剩余部分)dd
:删除文件的最后一行(FAKE SECTION
)
您可能想:set lazyredraw
加快宏执行速度。