我有一堆文件:
adenine-N1_B+1,70_A+0,00.pdb
adenine-N1_B+1,70_A-10,00.pdb
adenine-N1_B+1,70_A+10,00.pdb
adenine-N1_B+1,70_A-15,00.pdb
adenine-N1_B+1,70_A+15,00.pdb
adenine-N1_B+1,70_A-20,00.pdb
adenine-N1_B+1,70_A+20,00.pdb
adenine-N1_B+1,70_A-25,00.pdb
adenine-N1_B+1,70_A+25,00.pdb
adenine-N1_B+1,70_A-30,00.pdb
adenine-N1_B+1,70_A+30,00.pdb
adenine-N1_B+1,70_A-5,00.pdb
adenine-N1_B+1,70_A+5,00.pdb
我想按数字排序以获得以下内容:
adenine-N1_B+1,70_A-30,00.pdb
adenine-N1_B+1,70_A-25,00.pdb
adenine-N1_B+1,70_A-20,00.pdb
adenine-N1_B+1,70_A-15,00.pdb
adenine-N1_B+1,70_A-10,00.pdb
adenine-N1_B+1,70_A-5,00.pdb
adenine-N1_B+1,70_A+0,00.pdb
adenine-N1_B+1,70_A+5,00.pdb
adenine-N1_B+1,70_A+10,00.pdb
adenine-N1_B+1,70_A+15,00.pdb
adenine-N1_B+1,70_A+20,00.pdb
adenine-N1_B+1,70_A+25,00.pdb
adenine-N1_B+1,70_A+30,00.pdb
是否有排序命令可以执行此操作?到目前为止,我有以下内容:
for i in $(ls *.pdb | sort -V); do echo $i; done
答案1
总结
ls *.pdb | sort -k 1.20g
(是的,我知道这等等;请参阅下面的陷阱部分)。
排序逻辑
sort -g
您需要的是常规数字排序( ),但您应该指定数字的开始位置。
您的例子的形式如下:
adenine-N1_B+1,70_A-15,00.pdb
^ the number starts here: character 20, always
没有空格,因此 plainsort
将整个文件名视为一个字段。您需要从第一个字段的第 20 个字符开始的一般数字排序:
sort -k 1.20g
您可能希望引入更复杂的逻辑。例如,如果其中一个条目是bogonine-X3_B+1,00_A-12,00.pdb
,则像这样分解条目将非常合理:
foo_bar_A+00,00.pdb
^ ^ field separators
^ first field starts here
^ third field starts here
^ the number starts here: field 3, character 2
并根据第一个字段进行排序,然后按这些数字排序,如下所示:
sort -t '_' -k 1,1 -k 3.2g
(比较这个答案)。
区域设置
环境指定的语言环境会影响排序顺序。您可能会遇到建议以防LC_ALL=C
万一。这可能是也可能不是您想要的,取决于您是否要将最后一个逗号 ( ,
) 视为小数分隔符(好吧,您,00
在每个条目中都有,所以这实际上并不重要;但总的来说这很重要)。
如果您只需要为一次特定的调用更改语言环境sort
,则方法如下:
LC_ALL=C sort …
各种方法的缺陷
这是您尝试过的:
for i in $(ls *.pdb | sort -V); do echo $i; done
该命令过于复杂,内部部分基本完成相同的工作:
ls *.pdb | sort -V
ls
解析is的输出不是一个好主意,尽管您的示例文件名非常安全,所以您应该可以摆脱它。请注意,您ls
根本不需要:
for i in *.pdb; do echo "$i"; done | sort …
问题ls *.pdb
是你可能会遇到argument list too long
错误(当然,不是在你的示例中,而是一般情况下)。语法for i in *.pdb; …
是免疫的。
echo
您的示例名称似乎也可以安全地使用(看到普遍的问题echo
)。它们不包含特殊字符,因此您不需要find … -print0
norsort -z …
等。