我需要處理 .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";
}
檔案示例名稱:"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>
我的目的是從檔案中提取日期字串“20140911”,并存盤到一個新變數“sdate”中
通過這種方式,我需要有兩個變數,所以我可以與名稱和日期進行比較
是否可以直接從txt檔案的名稱中提取像“20140911”這樣的年月日?
uj5u.com熱心網友回復:
總是可以使用簡單的正則運算式決議這樣的字串
my $file = 's-ar-ar55g-1_20140911-09.txt';
my ($sname, $date) = $file =~ /( [^_] ) _ ( [0-9]{8} )/x;
該/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
在第二的是第三個引數split,將2告訴split干脆回傳兩個元素。所以這將是第-一個之前的內容,然后是一個字串,之后是所有內容。
我們需要()在周圍$date強制一個串列背景關系,否則它會強制一個標量背景關系并被分配回傳串列的元素數量(2)。
顯然,首先比基本的正則運算式要多一些作業和考慮。
另一種方式,以進一步推動該引數,將split在任_或-,然后根據需要組裝部件
my @parts = split /[_-]/, $file;
my ($sname, $date) = ( join('-', @parts[0..3]), $parts[4] );
現在我們還有那個@parts變數浮動,據說是不需要的,所以讓我們避免命名空間污染
my ($sname, $date) = do {
my @parts = split /[_-]/, $file;
join('-', @parts[0..3]), $parts[4];
};
(現在@parts,在該塊內被宣告為詞法my ,在它do之外不存在。)
當字串的一部分需要分析和處理時,這是使用字串的標準方法,但與那個簡單的正則運算式相比,這顯然是一種矯枉過正。
uj5u.com熱心網友回復:
以下代碼片段利用正則運算式從檔案名 4 部分中提取/捕獲:下劃線之前的任何內容、年份(前 4 位數字)、月份(接下來的 2 位數字)、月份中的某天(接下來的 2 位數字)——為了完整性檢查需要破折號與以下內容2 位數字,點和 txt 作為檔案的擴展名。
輸出連接日期部分/僅用于演示目的。
注:更換while( <DATA> ) {用for ( glob('s-ar-*.txt') ) {得到的文本檔案匹配的檔案串列面具的檔案系統。
use strict;
use warnings;
use feature 'say';
while( <DATA> ) {
/([^_]*)_(\d{4})(\d{2})(\d{2})-\d{2}\.txt/;
my($switch,$year,$month,$mday) = ($1,$2,$3,$4);
say "Switch name: $switch - Date: " . join('/',$year,$month,$mday);
}
__DATA__
s-ar-ar55g-1_20140911-09.txt
s-ar-ar55g-1_20141027-09.txt
輸出
Switch name: s-ar-ar55g-1 - Date: 2014/09/11
Switch name: s-ar-ar55g-1 - Date: 2014/10/27
參考:Perl 正則運算式
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/316278.html
