你如何完全避免使用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]<<
地球上的你是什麼試圖在這裏做:'$ {EMAIL/@/\\ @}'? – TLP
@TLP是用於替換的可變擴展的bash語法。 – wjl
也許你應該嘗試用's/here/\ $ ENV {EMAIL} /'替換's/here/$ EMAIL /'。你在Perl中如何訪問環境變量。並且/或者也可以將''''改成'''',這樣你或許可以刪除反斜槓。 – TLP