我希望在s
最后一次出现之后按数字对文件名进行排序,怎么做?
例如:
01002M00T1relaxouspios1001a001.nii
01002M00T1relaxos301a001.nii
01002M00T1relaxos201a001.nii
01002M00T1relaxouspios901a001.nii
排序的文件名应为:
01002M00T1relaxos201a001.nii
01002M00T1relaxos301a001.nii
01002M00T1relaxouspios901a001.nii
01002M00T1relaxouspios1001a001.nii
我尝试使用
$sort -ts -nk2,4
但它仅适用于前2个文件名。
示例2:
01002M00T1relaxos201a001.nii
01002M00T1relaxouspios1001a001.nii
01002M00T130relaxos301a001.nii
01002M00T130relaxouspios901a001.ni
预期产出:
01002M00T1relaxos201a001.nii
01002M00T130relaxos301a001.nii
01002M00T130relaxouspios901a001.ni
01002M00T1relaxouspios1001a001.nii
答案 0 :(得分:2)
简单,使用-V
选项进行版本排序:
$ sort -V file
01002M00T1relaxos201a001.nii
01002M00T1relaxos301a001.nii
01002M00T1relaxouspios901a001.nii
01002M00T1relaxouspios1001a001.nii
编辑第二个示例后编辑。
一般案例:
$ ls | awk -Fs '{print $NF, $0}' | sort -n | awk '{print $2}'
01002M00T1relaxos201a001.nii
01002M00T130relaxos301a001.nii
01002M00T130relaxouspios901a001.ni
01002M00T1relaxouspios1001a001.nii
答案 1 :(得分:2)
你可以使用像Perl或Python这样的编程语言,它可以让你更多地指定你想要排序的东西,但是如果你坚持使用BASH,你将不得不采用一个小技巧:
您可以使用sed
创建排序键,根据您创建的排序键进行排序,然后使用`sed:
ls | sed 's/\(.*s\)\(.*\)/\1\2 ^ \2)
以上使用正则表达式的贪婪能力来获得你想要的东西。 \(.*s\)
会将所有内容与最终小写s
匹配。 \(.*\)
将匹配s
的所有内容。 \1
和\2
匹配\(...\)
组中捕获的各个部分。因此,我有两个字符串;第一个是文件名,第二个是排序字符串。输出将如下所示:
$ ls | sed 's/\(.*s\)\(.*\)/\1\2 ^ \2/'
01002M00T1relaxouspios1001a001.nii ^ 1001a001.nii
01002M00T1relaxos301a001.nii ^ 301a001.nii
01002M00T1relaxos201a001.nii ^ 201a001.nii
01002M00T1relaxouspios901a001.nii ^ 901a001.nii
现在,我可以在^
:
$ ls | sed 's/\(.*s\)\(.*\)/\1\2 ^ \2/' | sort -t^ -k2.2
01002M00T1relaxouspios1001a001.nii ^ 1001a001.nii
01002M00T1relaxos201a001.nii ^ 201a001.nii
01002M00T1relaxos301a001.nii ^ 301a001.nii
01002M00T1relaxouspios901a001.nii ^ 901a001.nii
现在,我所要做的就是删除那个排序键:
$ ls | sed 's/\(.*s\)\(.*\)/\1\2 ^ \2/' | sort -t^ -k2.2| sed 's/ ^ .*//'
01002M00T1relaxouspios1001a001.nii
01002M00T1relaxos201a001.nii
01002M00T1relaxos301a001.nii
01002M00T1relaxouspios901a001.nii
答案 2 :(得分:2)
如果数字为uniq 并且足以成为索引,则有一个优雅的 bash only 解决方案。
我们的想法是使用bash array
但不使用associative
:
unset sortedlist
declare -a sortedlist
while read filename;do
[[ $filename =~ s([0-9]+)[a-rt-z][^s]*$ ]] &&
sortedlist[${BASH_REMATCH[1]}]=$filename
done < <(ls)
printf "%s\n" "${sortedlist[@]}"
01002M00T1relaxos201a001.nii
01002M00T1relaxos301a001.nii
01002M00T1relaxouspios901a001.nii
01002M00T1relaxouspios1001a001.nii
注意:在数组中,字段按数字顺序排序,因此1001
大于901
。
Nota2:由于[[ ... =~ ... ]]
是一个条件,因此只会忽略与正则表达式不匹配的文件名。