2014-04-16 46 views
1

我正在試驗sed,最近我注意到有趣的行爲。但是,我無法找到任何描述它的文檔。Sed:在's'命令行匹配正則表達式的反向引用substring

假設我們有文件名爲 'sedtest':

$cat sedtest | sed '/\([[:digit:]]\+\)/s,,(\1),' 
hello (0) world 
example 
(4) sed 
Phone number: (123)-456-789 

這是非常容易理解的sed腳本:

$cat sedtest 
hello 0 world 
example 
4 sed 
Phone number: 123-456-789 

接下來,我將通過sed的運行

  1. 首先,它通過regexp \([[:digit:]]\+\)匹配字符串,表示「匹配包含1個或多個數字的字符串」。請注意,我還使用s命令式\(\)圓括號在此標記子字符串(是否允許?)。
  2. 如果匹配,則執行s命令s,,(\1),(帶有空的正則表達式字段),表示「用(\1)替換匹配的子字符串」。

起初我認爲它應該失敗,出現錯誤,因爲\1和類似的反向引用應該只工作從s命令匹配字段,它是在這種情況下,空的字符串。

但結果好像是s,\([[:digit:]]\+\),(\1),腳本(\regexp\匹配器移到s命令匹配器字段中)!

所以,問題是:它是正常的(即,它是希望的行爲),就好像它們是由s/regexp/replace/命令匹配反向引用從s//replace/命令通過\regexp\規則匹配的文本的子串?

P.S.

我的sed版本:GNU的sed 4.2.1

背後問題的動機是這樣,你可以這樣做:

sed '/^Number: \([[:digit:]]\+\)$/{s,,#NUMBER: (\1),;p;d};q 1',即

  1. /^Number: \([[:digit:]]\+\)$/ - 每個字符串匹配Number: 12345和匹配的情況:
    • s,,#NUMBER: (\1), - 用替換它
    • p - 打印
    • d - 圖案清晰的空間,和開始新的循環(取新行和開始解析從開始腳本表達式)
  2. q 1 - 出口與代碼1,該命令僅在步驟1中沒有發生匹配時執行(因爲d命令存在) - 它檢查'不匹配'的情況,在我的情況下這意味着'不允許字符串'並且必須導致錯誤。

主這裏特技正在執行pd命令置換髮生,使用「正常」 s/match/replace/命令時,這是不可能的之後。

回答

1

這很正常。除非您做另一次匹配,否則後置參考保持空間不會被清除。由於s的正則表達式爲空,因此\1指向之前的捕獲組。你可以看到區別:

$ sed '/\([[:digit:]]\+\)/s,\(a\),(\1),' sedtest 
hello 0 world 
example 
4 sed 
Phone number: 123-456-789 

沒有匹配(線,數字也有a,但後面引用存放被清除

$sed '/\([[:digit:]]\+\)/s,\(e\),(\1),' 
h(e)llo 0 world 
example 
4 s(e)d 
Phon(e) number: 123-456-789 

e匹配,並且變爲後方參考

如果你不想要這種行爲,你不應該通過把\(\)放在[[:digit:]]之前來創建反向參考。