2014-01-16 65 views
3

我想爲只匹配有效域的grep做一個正則表達式。grep有效的域正則表達式

我的版本的工作還算不錯,但符合以下無效域:

@subdom..dom.ext 

這裏是我的正則表達式:

echo "@dom.ext" | grep "^@[[:alnum:]]\+[[:alnum:]\-\.]\+[[:alnum:]]\+\.[[:alpha:]]\+\$" 

我使用bash工作,所以我逃特殊字符。

樣品應符合:

@subdom.dom.ext 
@subsubdom.subdom.dom.ext 
@subsub-dom.sub-dom.ext 

感謝您的幫助

+0

如果有必要準確grep和比賽唯一的現有頂級域名的,看看https://stackoverflow.com/questions/14460680/how-to-get-a- list-of-tlds-using-bash-for-building-a-regex –

回答

6

一個真正完整的解決方案需要更多的工作,但這裏有一個鏡頭(注意,@前綴假設):

^@(([a-zA-Z](-?[a-zA-Z0-9])*)\.)*[a-zA-Z](-?[a-zA-Z0-9])+\.[a-zA-Z]{2,}$ 

你可以用egrep(或grep -E)使用,也可與[[ ... =~ ... ]],bash的正則表達式匹配運算符。

做以下假設,它比實際的DNS名稱的限制更寬鬆:

  • 只有ASCII(非外資)字母被允許 - 請參閱下面的國際化域名(IDN)的考慮;還有,IDN的ASCII形式 - 例如xn--bcher-kva.chbücher.ch) - 不匹配(儘管它很容易解決)。
  • 對嵌套子域的數量沒有限制。
  • 對任何標籤(名稱組件)的長度沒有限制,對名稱的總長度沒有限制(實際限制見here)。
  • TLD(最後一個組件)僅由字母組成,其長度至少爲2.
  • 子域和域名都必須以字母開頭;該域名的長度必須至少爲2;子域允許爲單字母。

下面是一個簡單的測試:

for d in @subdom..dom.ext @dom.ext @subdom.dom.ext @subsubdom.subdom.dom.ext @subsub-dom.sub-dom.ext; do 
[[ $d =~ \ 
    ^@(([a-zA-Z](-?[a-zA-Z0-9])*)\.)*[a-zA-Z](-?[a-zA-Z0-9])+\.[a-zA-Z]{2,}$ \ 
]] && echo YES || echo NO 
done 

支持Internationalized Domain Names (IDN)

一個簡單的改進,也符合國際化域名是在[[:alnum:]][[:alpha:]][a-zA-Z0-9]更換[a-zA-Z]以上正則表達式;即:

^@(([[:alpha:]](-?[[:alnum:]])*)\.)*[[:alpha:]](-?[[:alnum:]])+\.[[:alpha:]]{2,}$ 

注意事項

  • 並非所有的類Unix平臺對[[:alpha:]][[:alnum:]]匹配時,完全支持所有的Unicode字符。例如,使用基於UTF-8的語言環境,OS X 10.9.1顯然只匹配拉丁變音符號(例如,ü,á)和西里爾文字符(除ASCII之外),而Linux 3.2似乎涵蓋所有腳本,包括亞洲和阿拉伯語。

  • 我不清楚從右到左書寫腳本中的名稱是否正確匹配。

  • 爲了完整起見:即使上述正則表達式不試圖強制執行長度的限制,試圖與國際化域名這樣做會更復雜,因爲篇幅所限適用於ASCII編碼名稱(通過Punycode),而不是原來的。

@Alfe指出IDN問題的提示。

+0

不錯的解釋是不是這個更小?^@(([a-zA-Z]( - ?[a-zA-Z0-9])*)\。)+ [a-zA-Z] {2,} $ – Arka

+0

@Arka:將允許無效的單字母域名(例如'@ a.com')。請注意,我的正則表達式中的第一個'( - ?[a-zA-Z0-9])'用於_sub_域 - 用'*'量化,而第二個 - 用於_domain_ - 用'+' 。 – mklement0

+0

你是對的,再次感謝。 – Arka

0
echo "@dom.ext" | grep -E "^@[a-zA-Z0-9]+([-.]?[a-zA-Z0-9]+)*.[a-zA-Z]+$" 

該做的工作。

+1

域可以以數字開頭? – Alfe

+0

此外,你需要逃避最後一次出現'.'。 – mklement0

1

使用

grep '@[[:alpha:]][[:alnum:]\-]*\.[[:alpha:]][[:alnum:]\-]*\.[[:alpha:]][[:alnum:]\-]*$' 
+0

您假設3個組件(子域),但OP也想匹配域(2個組件)。另外,TLD是否僅由字母組成(.com,.info,...)? – mklement0

+0

是的,沒錯。但是當進入這樣的細節時,我們也可以考慮unicode域(比如www.müller.de),那麼[az]也不夠,我擔心'grep'的'[[:alnum:]]''也可能會錯誤地處理這些變音(取決於編解碼器等)。所以我想我們可以按照你接受的答案來處理它。如果這對於OP是有效的,那應該就足夠了。不過,如果他想要有一個明確的答案,我認爲我們沒有足夠的,但是---) – Alfe

+1

好點,謝謝。我已更新了我的帖子,並提供了至少一些答案,並闡明瞭我的解決方案的侷限性。 – mklement0