PERL - 处理 txt 文件,并提取不同变量中的数据

sel*_*ika 3 regex perl split

我需要使用 .txt 文件,并按文件名中存储的名称和日期进行过滤。

目前我实现了以下目标:

my $dir = "t-files\/";
chdir($dir);
foreach $files (glob('*.txt')) {
  ($sname) = split(/_/, $files);
  #($sdate) = "still under work"
  print "\nSwitch Name: $sname - Date: still under work";
}
Run Code Online (Sandbox Code Playgroud)

文件示例名称:"s-ar-ar55g-1_20140911-09.txt" | "s-ar-ar55g-1_20141027-09.txt" |

使用此脚本我有以下输出:

D:\_perl>test_01.pl

Switch Name: s-ar-ar55g-1 - Date: still under work
Switch Name: s-ar-ar55g-1 - Date: still under work
Switch Name: s-ar-ar55g-1 - Date: still under work
Switch Name: s-ar-ar55g-1 - Date: still under work
Switch Name: s-ar-ar55g-1 - Date: still under work
Switch Name: s-ar-ar55g-1 - Date: still under work
Switch Name: s-ar-ar55g-1 - Date: still under work
Switch Name: s-ar-ar55g-1 - Date: still under work
Switch Name: s-ar-ar55g-1 - Date: still under work
D:\_perl>
Run Code Online (Sandbox Code Playgroud)

我的目的是从文件中提取日期字符串“20140911”,并将其存储到新变量“sdate”中

通过这种方式,我需要有两个变量,这样我就能够与名称和日期进行比较

是否可以直接从txt文件的名称中提取像“20140911”这样的年月日?

zdi*_*dim 5

总是可以使用简单的正则表达式解析这样的字符串

my $file = 's-ar-ar55g-1_20140911-09.txt';

my ($sname, $date) = $file =~ /( [^_]+ ) _ ( [0-9]{8} )/x;
Run Code Online (Sandbox Code Playgroud)

修饰符/x使它忽略#模式中的空格(和换行符,并尊重注释),以便我们可以使其更具可读性。至于模式,我^在字符类[]with中使用了否定 ( ) [^_],它匹配除 之外的任何字符_,下面的+意思是必须至少有一个这样的字符。这样就匹配了直到第一个字符的字符串_

这是被捕获的,因为周围有(),并且必须重复 8 次的数字的模式也是如此[0-9]{8}。返回两个捕获的模式,并将其分配给$sname$date。请参阅初学者教程perlretut,或者您最喜欢的 Perl 好书。

请注意,我my $sname在引入 和所有其他变量时声明了它们。这可以通过严格的编译指示来强制执行,当然,您也必须始终启用警告。


您使用的分割是一个很好的工具,但这里还有更多的事情要做

my ($sname, $date) = split /_/, $file;  
# Now need to remove the trailing `-1.txt` from $date
($date) = split /-/, $date, 2;
# or, with a regex
# $date =~ s/[^-]+\K.*//;  # remove the first - and all after it
Run Code Online (Sandbox Code Playgroud)

第二个中的第三个参数split告诉2我们split总共返回两个元素。所以这将是第一个之前的内容-,然后是一个字符串及其后面的所有内容。

我们需要()强制$date执行列表上下文,否则它将强加标量上下文,并被分配返回列表 ( ) 的元素数量2

显然,首先比基本的正则表达式 usd 需要更多的工作和考虑。

另一种方法是,进一步推动这一论点,即选择split_-然后根据需要组装零件

my @parts = split /[_-]/, $file;
my ($sname, $date) = ( join('-', @parts[0..3]), $parts[4] );
Run Code Online (Sandbox Code Playgroud)

现在我们还有这个@parts变量浮动,据说是不需要的,所以让我们避免命名空间污染

my ($sname, $date) = do {
    my @parts = split /[_-]/, $file;
    join('-', @parts[0..3]), $parts[4];
};
Run Code Online (Sandbox Code Playgroud)

(现在,在该块内@parts被声明为词法mydo,在该块之外不存在。)

当字符串的某些部分需要分析和处理时,这是处理字符串的标准方法,但与简单的正则表达式相比,这显然是一种矫枉过正的做法。