2013-11-25 60 views
0

你如何完全避免使用s//運算符的perl替換的REPLACEMENT部分?\Q\E工作的,如下圖所示:如何在perl替換中轉義REPLACEMENT?

爲背景,用perl做大遞歸搜索並替換bash腳本驅動的操作時,此出現。這不是一個容易避免的情況。

拿這個腳本,例如:

$ cat example.sh 
#!/bin/bash 
set -v -x 
[email protected] 
echo "EMAIL = $EMAIL" 
echo "Email address: here" | perl -p -e "s/here/$EMAIL/" 
echo "Email address: here" | perl -p -e "s/here/\\Q$EMAIL\\E/" 
echo "Email address: here" | perl -p -e "s/here/${EMAIL/@/\\@}/" 

讓我們來運行它:

$ ./example.sh 
[email protected] 
+ [email protected] 
echo "EMAIL = $EMAIL" 
+ echo 'EMAIL = [email protected]' 
EMAIL = [email protected] 

到目前爲止好。 shell並沒有改變任何東西,我們正在迴應我們的期望。

echo "Email address: here" | perl -p -e "s/here/$EMAIL/" 
+ echo 'Email address: here' 
+ perl -p -e s/here/[email protected]/ 
Email address: user.org 

好了,到時候更換了沒有報價,因此字符串的@example部分得到了擴展(更不用說)和有效地消失了。好,好,讓我們與我們的好朋友\Q\E逃避它:

echo "Email address: here" | perl -p -e "s/here/\\Q$EMAIL\\E/" 
+ echo 'Email address: here' 
+ perl -p -e 's/here/\[email protected]\E/' 
Email address: user\.org 

嗯,這是意外! \Q\E引用.,但他們離開@example部分未經轉義!這裏發生了什麼?

echo "Email address: here" | perl -p -e "s/here/${EMAIL/@/\\@}/" 
+ echo 'Email address: here' 
+ perl -p -e 's/here/user\@example.org/' 
Email address: [email protected] 

好了,所以這最後的工作,但只是因爲我們使用bash的模式擴展到執行搜索和替換。它在這個特定的情況下工作,因爲這是一個電子郵件地址。在更一般的情況下,對於所有可能的替換元字符來說,這將是令人難以置信的繁瑣。

那麼,如何在使用s//運算符時完全避免perl替換的REPLACEMENT部分?可能嗎?必須有一個我錯過的絕招。 =)

解決使用s''',解決了這個簡單的例子

YSTH的回答表明,但我不能使用,在我真正的代碼,因爲我需要向引用在我的實際使用CAES。但是,ysth的回答和TLP的評論都提出使用$ENV{...}。據我所知,這在我的真實用例中完美工作,它必須能夠使用反向引用。

這是上面顯示的示例的更新版本。

它工作正常運行時:

$ ./example-new.sh 
[email protected] 
+ [email protected] 
# Don't touch my delimiters! 
echo "Email address goes >>>>>>here<<" | perl -p -e 's/(>+)here(<+)/$1$ENV{EMAIL}$2/' 
+ echo 'Email address goes >>>>>>here<<' 
+ perl -p -e 's/(>+)here(<+)/$1$ENV{EMAIL}$2/' 
Email address goes >>>>>>[email protected]<< 
+0

地球上的你是什麼試圖在這裏做:'$ {EMAIL/@/\\ @}'? – TLP

+0

@TLP是用於替換的可變擴展的bash語法。 – wjl

+1

也許你應該嘗試用's/here/\ $ ENV {EMAIL} /'替換's/here/$ EMAIL /'。你在Perl中如何訪問環境變量。並且/或者也可以將''''改成'''',這樣你或許可以刪除反斜槓。 – TLP

回答

3

\ Q \ E的應用變量代換的結果,所以你不能保持@example從插值的方式。

但是你可以使用單引號:

#!/bin/bash 
set -v -x 
[email protected] 
echo "Email address: here" | perl -p -e "s'here'$EMAIL'" 

或者,如果電子郵件地址可能包含'\\,讓Perl中得到$從環境EMAIL:

export [email protected] 
echo "Email address: here" | perl -p -e 's/here/$ENV{EMAIL}/' 
+0

單-quotes方法在某些實際情況下不起作用,因爲替換方法也使用'$ 1'等,但是'$ ENV {...}'方法看起來好像完全可以工作, – wjl

+0

不適用於$ 1 ';你能用預期的輸出顯示這種用法的例子嗎? – ysth

+0

我用SOLUTION部分更新了我的問題,以顯示你的'$ ENV {...}'建議如何處理我需要的'$ 1' – wjl