使用perl的RegEx使用组从文件路径中提取信息

时间:2015-10-31 20:19:40

标签: regex perl

所以我需要采用这种格式的东西:2015-08-15_15-41-32_44100_logo.txt并使用这两段代码从中提取日期,时间和频率。现在它的形式是<date>_<time>_<frequency>_logo.txt.以下是我试图使它成为一个正则表达式,但我知道我错过了一些东西。如何在perl中使用组来执行此操作? 下面的代码在目录中搜索模式后面的每个文件路径,并在列表中返回这些文件。我需要帮助的是正则表达式本身。我需要能够获得频率。

$pattern =qr/^(\d+)-(\d+)-(\d+)_(\d+)-(\d+)-(\d+)_44100_(\w+).(\w+)$/;
@listFiles = grep_files($bee_music_dir,$pattern);
print join(",",@listFiles);

sub grep_files {
    my ($dir, $pat) = @_;
    opendir(my $dir_handle, $dir) or die $!;
    my @files = grep { $_ =~ /$pat/ } readdir($dir_handle);
    closedir($dir_handle);
    return \@files;
}

2 个答案:

答案 0 :(得分:0)

你很亲密,只是做了一些改变。这是脚本和测试运行:

$ cat freq.pl
#!/usr/bin/perl --

use strict;
use warnings;

my $pattern = qr/^(\d+)-(\d+)-(\d+)_(\d+)-(\d+)-(\d+)_(\d+)_(\w+).(\w+)$/;

sub grep_files {
    my ($dir, $pat) = @_;
    opendir(my $dir_handle, $dir) or die $!;
    my @files = grep { $_ =~ /$pat/ } readdir($dir_handle);
    s/$pat/$7/ foreach @files;
    closedir($dir_handle);
    \@files;
}

print join("\n", @{grep_files '.', $pattern}), "\n";
$ ls
2015-08-15_15-41-32_44100_logo.txt  freq.pl
2015-08-25_25-41-32_48000_logo.txt
$ ./freq.pl
44100
48000

freq.pl从当前目录中的文件名中提取频率。它基于你的,有一些关键的区别:

  • 您将模式与未定义的变量匹配。您确实希望将模式存储在变量中。我也在开始和结束时锚定模式,所以在(在这种情况下不可能发生的事件)你有其他文件在开始或结束的东西,它不会意外地匹配那些。你还在线的末尾错过了一个分号。
  • 您正在选择与模式匹配的文件,但之后不提取频率。 s/$pat/$7/ foreach @files;遍历与模式匹配的所有文件,并用第7组替换所有文件,即频率。您还可以使用map代替grep一步选择文件并提取频率。
  • 我添加了最后一行进行测试。
  • 虽然没有直接关联,但请始终在脚本顶部使用use strictuse warningsuse strict会产生一些可疑的构造错误,use warnings会警告脚本可能出现的一些问题。

ls显示当前目录中的示例文件,freq.pl运行显示输出的脚本。

答案 1 :(得分:0)

perl中的正则表达式组使用如下:

my ($a, $b, $c) = $somestring=~ /(\d+)-(\d+)-(\d+)/;

此处,列表($a, $b, $c)中的每个变量都会分配匹配组的值,这些组也可用作$1$2$3。所以上面这行等同于:

$somestring =~ /(\d+)-(\d+)-(\d+)/;
my ($a, $b, $c) = ($1, $2, $3);

(你甚至可以做my $a = $1; my $b = $2; my $c = $3)。

如果你想声明一个$pattern变量,你应该这样做:

my $pattern = qr/(\d+)-(\d+)-(\d+)_(\d+)-(\d+)-(\d+)_(\d+)_(\w+).(\w+)/;

其中qrquote-regexp运算符,预编译正则表达式以进行优化。您不应在此处使用=~运算符,因为它会将正则表达式应用于$pattern,而不是将$pattern定义为正则表达式。 以这种方式定义图案只允许

$stringtomatch =~ $pattern;

(但=~ /$pattern/也可以。)

用于匹配格式为2015-08-15_15-41-32_44100_logo.txt<date>_<time>_<frequency>_logo.txt的文件的正则表达式如下所示:

/^(\d\d\d\d)-(\d\d)-(\d\d)_(\d\d)-(\d\d)-(\d\d)-(\d+)_logo\.txt$/

您可以使用\d+,但不一定与日期匹配。此外,正则表达式中的.表示“任何字符”,因此如果您的意思是.,则应该将其转义:\.

以下是您的子部分的更详细版本,说明了对群组的访问:

my @files = ();
while ( my $file = readdir($dir_handle) ) {
   if ( my ($year,$month,$day,$hour,$minute,$second,$freq) = $file =~ $pattern ) {
       # do something with $freq
       push @files, $file;
   }
}

如果你所追求的只是一个频率列表,那么仅对所需字段进行“分组”就足够了:

my $pattern = qr/^\d+-\d+-\d+_\d+-\d+-\d+_(\d+)_logo\.txt$/;