1

我想按最后一次出现后的数字对文件名进行排序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 
4

3 回答 3

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
于 2012-11-30T12:47:25.943 回答
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
于 2012-11-30T14:52:36.363 回答
2

如果数字唯一的并且足以成为索引,则有一个优雅的bash only解决方案。这个想法是使用但不是:bash arrayassociative

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

注意2:作为[[ ... =~ ... ]]一个条件,与正则表达式不匹配的文件名将被忽略。

于 2012-11-30T15:32:48.630 回答