2016-04-05 97 views
-4

我需要sed命令將電話號碼格式從999-999-9999更改爲(999)999-9999。 這是我一直想:我需要一個sed命令將電話號碼格式從999-999-9999更改爲(999)999-9999

sed 's/[[:digit:]]\-[[:digit:]]\-[[:digit:]]/\([[:digit:]]\)[[:digit:]]\-[[:digit:]]/gp' 

我也試過這樣:

sed 's/([0-9]{3})\-([0-9]{3})\-([0-9]{4})/\(([0-9]{3}\))([0-9]{3})\-([0-9]{4})/gp' 
+0

'[[:digit:]]'單位匹配一個數字,而不是三位數。 –

回答

2

的符號[[:digit:]]一個單一的數字相匹配;你需要匹配重複的數字,這是通過在\{3\}中包裝重複計數來完成的(對於固定計數;也有可變計數範圍,但它們在這裏不相關,並且*等等)。並且您需要捕獲您在\(…\)中匹配的內容,以便在替換中引用它們。在替換中,您使用\1等來指代捕獲的片段。捕捉按照\(符號的順序從左到右編號。

sed 's/\([[:digit:]]\{3\}\)-\([[:digit:]]\{3\}-[[:digit:]]\{4\}\)/(\1)\2/g' 

或者:

sed 's/\([0-9]\{3\}\)-\([0-9]\{3\}-[0-9]\{4\}\)/(\1)\2/g' 

這是經典的sed符號;您也可以使用擴展正則表達式來查找變體,但根據平臺需要不同的選項,與此不同。模式查找3位數字(第一次捕捉),一個破折號,然後3個數字,另一個破折號和4位數字作爲第二次捕獲,並用開括號(美式括號),前3位數字,右括號,其餘3位數字,短劃線,4位數字。

BSD鍵(Mac OS X):

sed -E 's/([0-9]{3})-([0-9]{3}-[0-9]{4})/(\1)\2/g' 

GNU:

sed -r 's/([0-9]{3})-([0-9]{3}-[0-9]{4})/(\1)\2/g' 

注意,所有這些正則表達式會轉換

9876-345-54321 

到:

9(876)345-54321 

修復不那麼無關緊要,特別是在sed。使用Perl:

$ echo "987-654-3210 and 2987-654-and 222-333-4444 and 543-432-5544" | 
> perl -p -e 's/\b([0-9]{3})-([0-9]{3}-[0-9]{4})\b/(\1)\2/g' 
(987)654-3210 and 2987-654-and (222)333-4444 and (543)432-5544 
$ 

\b在PCRE中標記了一個字邊界。這確實意味着a222-333-4444與Perl不匹配;你可以改進一些東西來堅持非數字或字符串的開始,以及非字符串或字符串結束後的匹配字符串。

$ echo "987-654-3210 and 2987-654-and a222-333-4444 and 543-432-5544" | 
> perl -p -e 's/(^|\D)([0-9]{3})-([0-9]{3}-[0-9]{4})(\D|$)/\1(\2)\3\4/g' 
(987)654-3210 and 2987-654-and a(222)333-4444 and (543)432-5544 
$ 

或用(BSD或GNU)sed擴展正則表達式(顯示BSD):

$ echo "987-654-3210 and 2987-654-and a222-333-4444 and 543-432-5544" | 
> sed -E 's/(^|[^0-9])([0-9]{3})-([0-9]{3}-[0-9]{4})([^0-9]|$)/\1(\2)\3\4/g' 
(987)654-3210 and 2987-654-and a(222)333-4444 and (543)432-5544 
$ 

需要注意的是,如果你想在否定數字字符類符號可以寫[^[:digit:]]

迭代開發有幫助。

+0

太棒了,謝謝!你能解釋一下這個部分究竟做了什麼,(\ 1)\ 2 /? – Edwin

+0

在第一個變種中,'\(... \)''捕獲'匹配項的一部分。在替換中,你可以根據需要經常引用那些被捕獲的片段(這裏是每個片斷),使用'\ 1'等來引用片段。這些片段按'\('符號出現的順序進行索引,所以'(\ 1)\ 2'用一個開括號,第一個3位數字組,一個右括號和第二個被捕獲的字符串(999-9999)。 –

+0

感謝您的所有幫助! – Edwin

1
$ echo 123-456-7890 | sed -r 's/([0-9]{3})-([0-9]{3}-[0-9]{4})/(\1)\2/' 
(123)456-7890 
+1

爲什麼不使用'awk'? – hek2mgl

+0

@ hek2mgl:因爲問題詢問了'sed'(通過標籤,並通過說明什麼已經嘗試過)。我沒有看到'awk'在這裏提供了很大的優勢;使用'gsub'或者其他等價物是可行的,但是如果有的話,這個符號比'sed'笨拙。 –

+0

我認爲這是一個笑話。 – karakfa