Bash 按上次出现字符后的数字对文件名进行排序
我想按上次出现Bash 按上次出现字符后的数字对文件名进行排序,bash,shell,Bash,Shell,我想按上次出现s后的数字对文件名进行排序,怎么做 例如: 01002M00T1relaxouspios1001a001.nii 01002M00T1relaxos301a001.nii 01002M00T1relaxos201a001.nii 01002M00T1relaxouspios901a001.nii 排序后的文件名应为: 01002M00T1relaxos201a001.nii 01002M00T1relaxos301a001.nii 01002M00T1relaxouspios90
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
简单地说,使用
-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\)\(.*\)/\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
您可以使用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
如果数字是uniq且足以作为索引,则有一个优雅的bash only解决方案。 想法是使用
bash数组
,而不是关联
:
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
unset-sortedlist
声明-分类列表
读取文件名时;做
[[$filename=~s([0-9]+)[a-rt-z][^s]*$]]&&
sortedlist[${BASH_重新匹配[1]}]=$filename
完成<如果数字为uniq且足以作为索引,则有一个优雅的bash only解决方案。
想法是使用bash数组
,而不是关联
:
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
unset-sortedlist
声明-分类列表
读取文件名时;做
[[$filename=~s([0-9]+)[a-rt-z][^s]*$]]&&
sortedlist[${BASH_重新匹配[1]}]=$filename
完成<否。这不起作用,例如:01002M00T1relaxos201a001.nii
01002M00T1relaxouspios1001a001.nii
01002M00T130relaxos301a001.nii
01002M00T130relaxouspios901a001。nii
这对您给出的示例有效,顺便说一句,欢迎您。Awk的有趣解决方案。使用$NF
并分离s
上的字段非常有趣。否。这不起作用,例如:01002M00T1relaxos201a001.nii
01002M00T1relaxouspios1001a001.nii
01002M00T130relaxos301a001.nii
01002M00T130relaxouspios901a001.nii
这适用于您给出的示例,顺便说一句,欢迎您。Awk的有趣解决方案。使用$NF
并分离s
上的字段非常有趣。非常感谢。它可以工作,除了这个小的修正:使用-nk2.2而不是-k2.2。更简单的方法是将钥匙放在前面,使用awk
更干净,请参阅我的更新答案。非常感谢。它可以工作,除了这个小的修正:使用-nk2.2而不是-k2.2。更简单的方法是把钥匙放在前面,使用awk
更干净,请参阅我的更新答案。我想我们对优雅的定义非常不同。是的,它是!在这种情况下,既没有用于sed
的fork,也没有用于排序的fork。一切都是相对的!我想我们对优雅的定义很不一样。是的,的确如此!在这种情况下,既没有用于sed
的fork,也没有用于排序的fork。一切都是相对的!