我需要根据第二列中包含的数字从最小到最大对 csv 填充中的所有行进行排序,忽略第一行(标题行):
ID(Prot), ID(lig), ID(cluster), dG(rescored), dG(before), POP(before)
10V1, lig1, 1, 0.893101, -7.2300, 36
10V1, lig1, 3, 1.04024, -6.5800, 4
10V1, lig1, 4, 1.03044, -6.5200, 7
10V1, lig10, 1, 0.895754, -6.0300, 47
10V1, lig10, 2, 0.668236, -5.9500, 112
10V1, lig10, 3, 1.0103, -5.8200, 19
10V1, lig1001, 1, 0.594972, -5.6500, 142
10V1, lig1001, 2, 1.05779, -5.5000, 10
10V1, lig1001, 3, 1.11195, -4.9500, 2
10V1, lig3, 1, 1.01583, -5.6000, 20
10V1, lig3, 2, 0.972203, -5.2600, 36
10V1, lig3, 3, 0.694967, -5.2400, 118
10V1, lig8, 1, 0.931977, -7.4000, 25
10V1, lig8, 2, 1.00413, -7.1100, 9
应按 lig1、lig3、lig8、lig10、lig1001 等排序:
ID(Prot), ID(lig), ID(cluster), dG(rescored), dG(before), POP(before)
10V1, lig1, 1, 0.893101, -7.2300, 36
10V1, lig1, 3, 1.04024, -6.5800, 4
10V1, lig1, 4, 1.03044, -6.5200, 7
10V1, lig3, 1, 1.01583, -5.6000, 20
10V1, lig3, 2, 0.972203, -5.2600, 36
10V1, lig3, 3, 0.694967, -5.2400, 118
10V1, lig8, 1, 0.931977, -7.4000, 25
10V1, lig8, 2, 1.00413, -7.1100, 9
10V1, lig10, 1, 0.895754, -6.0300, 47
10V1, lig10, 2, 0.668236, -5.9500, 112
10V1, lig10, 3, 1.0103, -5.8200, 19
10V1, lig1001, 1, 0.594972, -5.6500, 142
10V1, lig1001, 2, 1.05779, -5.5000, 10
10V1, lig1001, 3, 1.11195, -4.9500, 2
我试过了
sort -k2.4,2n "${csv}" > sorted.csv
但它不能正确识别第二个值。
答案1
默认情况下,sort
识别由非空白到空白转换分隔的字段。第二行的第二个字段(第一个是标题)不是 也不是lig1
,lig1,
而是lig1,
。
一开始并不清楚这个字段是否包含前导空格或制表符,因为这个网站在以下情况下将制表符转换为多个空格:显示代码。原料来源告诉我每行的第二个字段包含一个前导制表符。
此制表符算作字段中的第一个字符,因此您的-k2.4,2n
数字少了一个。它应该是-k2.5,2n
。
为了可靠地先打印标题而不对其进行排序,请让某些东西在sort
处理其余部分之前读取并打印它。它可以是你的 shell:
{ IFS= read -r line; printf '%s\n' "$line"; sort -k2.5,2n; } <"${csv}"
或者可以是head
:
{ head -n 1; sort -k2.5,2n; } <"${csv}"
在我的 Debian 10 中,这两个命令在从常规文件读取时都运行良好。从管道读取时(例如cat "${csv}" | { head …
),head
显然可能会读取过多并丢弃过多数据(因此sort
无法获取,数据会丢失)。
我猜测 head
即使从常规文件读取时也会读取更多内容,它只是在退出之前返回正确的位置,因此下一个工具可以从那里接管;对于不可搜索的输入,这显然是不可能的。
read
更加小心并且总是一次读取一个字节,因此它不会读取太多。