在perl中按生成顺序写入文件名

时间:2014-07-16 12:22:02

标签: perl

我在目录中有大约1000个文件。该文件的命名约定如下所示。

TC_01_abcd_16_07_2014_14_06.txt
TC_02_abcd_16_07_2014_14_06.txt
TC_03_abcd_16_07_2014_14_07.txt
.
.
.
.
TC_100_abcd_16_07_2014_15_16.txt
.
.
.
TC_999_abcd_16_07_2014_17_06.txt

我写了一些像这样的代码

my @dir="/var/tmp";
foreach my $inputfile (glob("$dir/*abcd*.txt")) {
print $inputfile."\n";
}

在运行时,它不是按顺序打印的。

它打印到09文件然后打印第1000个文件名然后

TC_01_abcd_16_07_2014_11_55.txt
TC_02_abcd_16_07_2014_11_55.txt
TC_03_abcd_16_07_2014_11_55.txt
TC_04_abcd_16_07_2014_11_55.txt
TC_05_abcd_16_07_2014_11_56.txt
TC_06_abcd_16_07_2014_11_56.txt
TC_07_abcd_16_07_2014_11_56.txt
TC_08_abcd_16_07_2014_11_56.txt
TC_09_abcd_16_07_2014_11_56.txt
TC_100_abcd_16_07_2014_12_04.txt
TC_101_abcd_16_07_2014_12_04.txt
TC_102_abcd_16_07_2014_12_04.txt
TC_103_abcd_16_07_2014_12_04.txt
TC_104_abcd_16_07_2014_12_04.txt
TC_105_abcd_16_07_2014_12_04.txt
TC_106_abcd_16_07_2014_12_04.txt
TC_107_abcd_16_07_2014_12_04.txt
TC_108_abcd_16_07_2014_12_05.txt
TC_109_abcd_16_07_2014_12_05.txt
TC_10_abcd_16_07_2014_11_56.txt
TC_110_abcd_16_07_2014_12_05.txt
TC_111_abcd_16_07_2014_12_05.txt
TC_112_abcd_16_07_2014_12_05.txt
TC_113_abcd_16_07_2014_12_05.txt
TC_114_abcd_16_07_2014_12_05.txt
TC_115_abcd_16_07_2014_12_05.txt
TC_116_abcd_16_07_2014_12_05.txt
TC_117_abcd_16_07_2014_12_05.txt
TC_118_abcd_16_07_2014_12_05.txt
TC_119_abcd_16_07_2014_12_06.txt
TC_11_abcd_16_07_2014_11_56.txt

请指导我如何按顺序打印

4 个答案:

答案 0 :(得分:1)

根据shell glob扩展规则对文件进行排序,这是一种简单的alpha排序。您需要根据第一个数字字段的数字排序对它们进行排序。

这是一种方法:

# Declare a sort comparison sub, which extracts the part of the filename
# which we want to sort on and compares them numerically.
# This sub will be called by the sort function with the variables $a and $b
# set to the list items to be compared
sub compareFilenames {
        my ($na) = ($a =~ /TC_(\d+)/);
        my ($nb) = ($b =~ /TC_(\d+)/);
        return $na <=> $nb;
}

# Now use glob to get the list of filenames, but sort them
# using this comparison
foreach my $file (sort compareFilenames glob("$dir/*abcd*.txt")) {
        print "$file\n";
}

请参阅:perldoc for sort

答案 1 :(得分:0)

按顺序打印文件 - ASCII顺序。

在ASCII中,下划线(_)位于排序后的数字之后。如果要按正确顺序对文件进行排序,则必须自行对其进行排序。如果没有sort,则无法保证他们可以按任何顺序打印。对你来说更糟糕的是,你真的不想以数字排序顺序打印文件(因为文件名不是数字)或ASCII顺序(因为你希望在TC_10之前打印TC_100 {1}}。

因此,您需要编写自己的排序例程。 Perl为您提供sort命令。默认情况下,它将按ASCII顺序排序。但是,您可以定义自己的子例程以按所需顺序排序。 sort会在您的排序例程$a$b中将两个值传递给您。您可以做的是解析这两个值以获取所需的排序键,然后使用<=>cmp运算符以正确的排序顺序返回值:

#! /usr/bin/env perl
use warnings;
use strict;
use autodie;
use feature qw(say);

opendir my $dir, 'temp';      # Opens a directory for reading
my @dir_list = readdir $dir;
closedir $dir;

@dir_list = sort {   # My sort routine embedded inside the sort command
    my $a_val;
    my $b_val;
    if ( $a =~ /^TC_(\d+)_/ ) {
        $a_val = $1;
    }
    else {
        $a_val = 0;
    }
    if ( $b =~ /^TC_(\d+)_/ ) {
        $b_val = $1;
    }
    else {
        $b_val = 0;
    }
    return $a_val <=> $b_val;
} @dir_list;


for my $file (@dir_list) {
    next if $file =~ /^\./;
    say "$file";
}

在我的sort子例程中,我将采用$a$b并提取您想要对其进行排序的数字,并将该值放入$a_val和{{ 1}}。如果文件没有我认为可能具有的名称,我还必须注意会发生什么。在这里,我只是决定将排序值设置为$b_val并希望最好。

我正在使用0opendir而非使用globbing。这最终会在我的列表中包含readdir.,并且它将包含以..开头的所有文件。没问题,我打印清单时会删除这些。

在我的测试中,打印出来:

.

文件按TC_01_abcd_16_07_2014_11_55.txt TC_02_abcd_16_07_2014_11_55.txt TC_03_abcd_16_07_2014_11_55.txt TC_04_abcd_16_07_2014_11_55.txt TC_05_abcd_16_07_2014_11_56.txt TC_06_abcd_16_07_2014_11_56.txt TC_07_abcd_16_07_2014_11_56.txt TC_08_abcd_16_07_2014_11_56.txt TC_09_abcd_16_07_2014_11_56.txt TC_10_abcd_16_07_2014_11_56.txt TC_11_abcd_16_07_2014_11_56.txt TC_100_abcd_16_07_2014_12_04.txt TC_101_abcd_16_07_2014_12_04.txt TC_102_abcd_16_07_2014_12_04.txt TC_103_abcd_16_07_2014_12_04.txt TC_104_abcd_16_07_2014_12_04.txt TC_105_abcd_16_07_2014_12_04.txt TC_106_abcd_16_07_2014_12_04.txt TC_107_abcd_16_07_2014_12_04.txt TC_108_abcd_16_07_2014_12_05.txt TC_109_abcd_16_07_2014_12_05.txt TC_110_abcd_16_07_2014_12_05.txt TC_111_abcd_16_07_2014_12_05.txt TC_112_abcd_16_07_2014_12_05.txt TC_113_abcd_16_07_2014_12_05.txt TC_114_abcd_16_07_2014_12_05.txt TC_115_abcd_16_07_2014_12_05.txt TC_116_abcd_16_07_2014_12_05.txt TC_117_abcd_16_07_2014_12_05.txt TC_118_abcd_16_07_2014_12_05.txt TC_119_abcd_16_07_2014_12_06.txt 之后的第一组数字进行数字排序。

答案 2 :(得分:0)

你走了:

#!/usr/bin/perl
use warnings;
use strict;

sub by_substring{
   $a=~ /(\d+)/;
   my $x=$1;
   $b=~ /(\d+)/;
   my $y=$1;
   return $x <=> $y;
}

my @files=<*.txt>;
@files = sort by_substring @files;
for my $inputfile (@files){
   print $inputfile."\n";
}

如果您的文件名以“TC”或“BD”或“President Carter”开头,这将无关紧要,这只会使用第一组相邻数字进行排序。

答案 3 :(得分:0)

目录中的排序将是字母数字,因此您的效果。我不知道如何按创建日期对glob进行排序,这是一个解决方法:

my @dir="/var/tmp";
my @files = glob("$dir/*abcd*.txt");
my @sorted_files;
for my $filename (@files) {
 my ($number) = $filename =~ m/TC_(\d+)_abcd/;
 $sorted_files[$number] = $filename;
}
print join "\n", @sorted_filenames;