在Perl中,如何從當前位置(最後一個替換位置)替換一個模式直到行尾?Perl:從當前位置替換模式直到行尾
我已經做了所有這些替代物在一個單一的線路:
...
s/\[//;
s/(\/\w\w\w\/)/ getMonth $1 /e;
s/:/ /;
s/\s\+\d\d\d\d\]//;
#NOW: replace all blanks with a plus sign from this position until the end of this line.
在Perl中,如何從當前位置(最後一個替換位置)替換一個模式直到行尾?Perl:從當前位置替換模式直到行尾
我已經做了所有這些替代物在一個單一的線路:
...
s/\[//;
s/(\/\w\w\w\/)/ getMonth $1 /e;
s/:/ /;
s/\s\+\d\d\d\d\]//;
#NOW: replace all blanks with a plus sign from this position until the end of this line.
因爲Perl 5.6,在最後比賽結束位置被存儲在@+
陣列英寸整場比賽結束時的位置是$+[0]
。
您可以使用此字符串分成兩個部分,並做纔有了後來的部分替代:
my $base = " pears apples bananas coconuts ";
$base =~ s/apples/oranges/;
my $firstpart = substr($base, 0, $+[0]);
my $secondpart = substr($base, $+[0]);
$secondpart =~ s/ /\+/g;
print '"' . $firstpart . $secondpart . "\"\n";
,它將打印:
這種方法" pears oranges+bananas+coconuts+"
一個問題是:即$+[0]
包含之前的位置的更換。所以也許有更好的辦法:)
將OP更好地替換這個序列的'/'操作會好得多「使用getMonth'返回的內容替換方括號中的月份+年份),並使用更簡潔的操作,並允許其餘的需求得到滿足。但是,這需要OP的合作。 – 2009-11-15 13:02:09
**'** + ** **是**不是**數組。 **'@ +'**是。我糾正了你的錯誤,並將其鏈接到文檔中的正確位置。回滾那些實際的更正(您可以輕鬆驗證)是不正確的。 http://perldoc.perl.org/perlvar.html#%40%2b – 2009-11-15 13:43:21
@SinanÜnür:如果你添加評論,我可以編輯我的答案,如果我同意(在這裏完成) – Andomar 2009-11-15 15:10:24
我看你接受了一個答案。然而,對於手頭的任務,那將是更適合使用Apache::ParseLog也許Apache::LogRegex:
Apache::LogRegex
- 解析從Apache日誌文件一行到一個哈希
它看起來對我來說,您正試圖從頭開始編寫日誌文件分析器,這是您按月分組日誌文件的方式。如果是這樣,請停止重新發明方形車輪。
即使你不想使用外部模塊,可以通過分割和征服使用split簡化任務:
#!/usr/bin/perl
use strict; use warnings;
use Carp;
use Regex::PreSuf;
my @months = qw(jan feb mar apr may jun jul aug sep oct nov dec);
my %months = map { $months[$_] => sprintf '%02d', $_ + 1 } 0 .. 11;
my $months_re = presuf(@months);
# wrapped for formatting, does not make any difference
my $str = q{62.174.188.166 - - [01/Mar/2003:00:00:00 +0100] "GET
/puntos/img/ganar.gif HTTP/1.1" 200 1551
"http://www.universia.com/puntos/index.jsp";
"Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt; Hotbar 2.0)"};
chomp($str);
my @parts = split qr{\s\[|\]\s}, $str;
if ($parts[1] =~ m!/($months_re)/!ix) {
$parts[1] = $1;
}
$parts[2] =~ s/\s/+/g;
print join(' ', @parts), "\n";
輸出:
62.174.188.166 - - Mar "GET+/puntos/img/ganar.gif+HTTP/1.1"+200+1551+"http://www .universia.com/puntos/index.jsp";+"Mozilla/4.0+(compatible;+MSIE+5.0;+Windows+98 ;+DigExt;+Hotbar+2.0)"
從你的語言,你似乎想象你的替換序列正在向前穿過字符串,每個替換佔據最後一個替換的地方。實際上,每個替代將適用於整個字符串。
當你說「最後一次替換的位置」時,如果前面的替換沒有發現,會發生什麼?
在腳本中,你可以做:
if (s/\s\+\d\d\d\d\]//) { $' =~ s/ /+/g }
但使用$應該在可重用的代碼來避免」,因爲它可能會影響其他正則表達式的性能。在那裏,你需要做的
if (s/\s\+\d\d\d\d\]//) { substr($_, $+[0]) =~ s/ /+/g }
但在這兩種情況下,你需要確保你所期望的匹配或替換已經設置$」或@ +真正成功。
請舉例說明您正在執行這些操作的輸入。 – 2009-11-15 12:43:55
這是一個Web服務器日誌行,我沒有在我的代碼示例中包含所有替換項。 62.174.188.166 - [01/Mar/2003:00:00:00 +0100]「GET /puntos/img/ganar.gif HTTP/1.1」200 1551「http://www.universia.com/puntos /index.jsp「」Mozilla/4.0(compatible; MSIE 5.0; Windows 98; DigExt; Hotbar 2.0)「 – Lucia 2009-11-15 13:12:45