按字符最后一次出现后的数字对文件名进行排序



我想按最后一次出现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 

很简单,使用 -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

你可以使用像Perl或Python这样的编程语言,让你更有能力指定你想要排序的内容,但如果你坚持使用BASH,你将不得不使用一个小技巧:

您可以使用 sed 创建排序键,根据您创建的排序键进行排序,然后使用 'sed:

ls | sed 's/(.*s)(.*)/12 ^ 2)

上面利用正则表达式的贪婪力量来得到你想要的东西。(.*s)会将所有内容与最终的小写s匹配。(.*)将匹配s的一切.12(...)组中捕获的各个部分相匹配。因此,我有两个字符串;第一个是文件名,第二个是排序字符串。输出将如下所示:

$ ls | sed 's/(.*s)(.*)/12 ^ 2/'
01002M00T1relaxouspios1001a001.nii ^ 1001a001.nii
01002M00T1relaxos301a001.nii ^ 301a001.nii
01002M00T1relaxos201a001.nii ^ 201a001.nii
01002M00T1relaxouspios901a001.nii ^ 901a001.nii

现在,我可以在^之后对部分进行排序:

$ ls | sed 's/(.*s)(.*)/12 ^ 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)(.*)/12 ^ 2/' | sort -t^ -k2.2| sed 's/ ^ .*//'
01002M00T1relaxouspios1001a001.nii
01002M00T1relaxos201a001.nii
01002M00T1relaxos301a001.nii
01002M00T1relaxouspios901a001.nii

如果数字是 uniq 并且足以成为索引,则有一个优雅的 bash 解决方案。这个想法是使用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 "%sn" "${sortedlist[@]}"
01002M00T1relaxos201a001.nii
01002M00T1relaxos301a001.nii
01002M00T1relaxouspios901a001.nii
01002M00T1relaxouspios1001a001.nii

Nota:在数组中,字段按数字顺序排序,因此1001大于 901

Nota2:由于[[ ... =~ ... ]]是一个条件,与正则表达式不匹配的文件名将被忽略。

最新更新