2010-01-25 67 views
2

我是新來的Perl,不知道如何實現以下。 我正在讀取一個文件並將這些行放在一個名爲$ tline的變量中。接下來,我試圖從$ tline中替換一些字符。如果$ TLINE具有一些特殊的字符,如 這種替代發生故障(,?,=等在裏面。如何從這個變量$ TLINE逃避特殊字符?爲什麼我的正則表達式會因某些替換而失敗?

if ($tline ne "") { 

    $tline =~ s/\//\%; 
} 

編輯

對不起,混淆。這裏是我想要做的事。

$tline =~ s/"\//"\<\%\=request\.getContextPath\(\)\%\>\//; 

這正在爲大多數情況下,但是當輸入文件有?於它,它失敗了。

+2

你究竟想要做什麼?你能給我們一個你正在使用的數據的樣本,以及你想要它成爲什麼?當你說替代品「失敗」時,你的意思是什麼? – 2010-01-25 20:52:42

+2

您的正則表達式似乎未封閉。 'S/\ // \%/'?這是一個錯字嗎?我建議如果你的表達式中有「/」,你應該使用不同的分隔符,如:'s |/|%|'。 – slebetman 2010-01-25 20:54:28

+0

檢查我的答案,更新引用quotemeta – 2010-01-25 21:05:35

回答

7

如何:

$tline =~ s/\Q$var\E/; 

這將導致quotemeta應用於正被用作模式的$var的內容。

+0

在我的情況下,$ var沒有任何特殊字符,但$ tline有。 – Shamik 2010-01-25 21:09:05

+0

對不起,正如我所說,我是Perl新手,這工作得很好。謝謝。 – Shamik 2010-01-25 21:17:27

2

這不是一個有效的正則表達式:

$tline =~ s/\//\%; 

它得到這樣寫的到perl

$tline =~ s/a/%; 

a = /

你想要做什麼是更換斜槓百分號你可能想要

$tline =~ s/\//%/; 

哪家好這樣寫的:

$tline =~ s,/,%,; 

您可能還需要更換的不僅僅是第一個正斜槓更多,所以你想要的/g標誌:

$tline =~ s,/,%,g; 

而且,這正是tr(音譯)所做的:

$tline =~ tr,/,%,; 

UPDATE我想你想要的是一個簡單的quotemeta()這需要你的輸入和正則表達式,轉義元字符

$ perl -e'print quotemeta("</foo?>")' 
\<\/foo\?\> 
1

你可以放置方括號(稱爲「字符類」)之間所有的特殊字符。下面將用百分號全部更換左括號,問號和等號在您的字符串:

my $tline = 'fo(?=o'; 
$tline =~ s/[(?=]/%/g; 
print "$tline\n"; 

打印:

fo%%%o 
+0

我需要找回我改變了,如果我改變所有?,=到%,我該如何找回他們? – Shamik 2010-01-25 21:10:58

+0

保存原始字符串的副本。 – toolic 2010-01-25 21:17:49

0

那麼,一種方法是把你想要替換的所有字符放在方括號中。像這樣:

$string =~ s/[,?=\/]//; # This will remove the first ',', '?', '=', or '/' from your string. 

如果你想刪除所有'?'在一個字符串,例如,使用AG在它的結束,像這樣:

$string =~ s/[?]//g; 

我有點生疏,但我相信,你只需要在\前面的「\」或/(當然還有其他特殊字符,比如\ n,\ t等等)。像這樣:

$string =~ s/[\\]/[\/]/g; # Switch from DOS to Unix delimiters. 

$string =~ s/[\n\t]//g; # Remove all newlines and tabs 

正如其他人所說,你發佈的代碼是不會工作,因爲你忘了最後一個/。這是將「奇怪」字符保存在一個盒子中的另一個好理由。

0

quotemeta是一個很好的函數,用於將具有特殊字符的精確文字轉換爲正則表達式。而\Q and \E是在正則表達式中做同樣事情的好運營商。

但是,你是搜索表達式並不那麼複雜。在你的編輯中,你只是在尋找一個雙引號和一個斜槓。事實上,我已經非常簡化了你的表達,所以它不包含一個反斜槓。所以這不是quotemeta也不是\Q and \E的問題。

一旦削減,我沒有看到任何修改後的替代品會導致'?'的問題。在$tline

關鍵的簡化是,‘(’和‘)’的意思是什麼特別的你表達的更換部分,所以這相當於「」:

$tline =~ s/"\//"<%=request.getContextPath()%>\//; 

且不說更容易閱讀。當然,這是更簡單:

$tline =~ s|"/|"<%=request.getContextPath()%>/|; 

因爲在Perl中,你可以選擇你想與soperator的分隔符。

但與任何這些,這個工程:

use Test::More tests => 1; 

my $tline = '"/?"'; 
$tline =~ s|"/|"<%=request.getContextPath()%>/|; 
ok($tline =~ /getContextPath/); 

它通過測試。也許你遇到了一個線路上多於一個替換的問題。可固定有:

$tline =~ s|"/|"<%=request.getContextPath()%>/|g; 

G是在端部的全球開關,說因爲它在輸入中發生使該取代多次。

但是,因爲我可以看到你在做什麼,我建議你要搜索的內容更加緊密規格:

$tline =~ s~\b(href|link|src)="/~$1="<%=2request.getContextPath()%>/~g; 

當我運行此:

use Test::More tests => 2; 

my $tline = '"/?"'; 
$tline =~ s/"\//"<%=request.getContextPath()%>\//; 
ok($tline =~ /getContextPath/); 
$tline = 'src="/?/?/beer"'; 
ok($tline =~ s~\b(href|link|src)="/~$1="<%=request.getContextPath()%>/~g 
    ); 

我得到兩個成功。

您的true問題尚未說明。