2011-05-25 26 views
5

我似乎無法順利建立在Haskell正則表達式,我想要做的是轉換這個字符串(這一段文字相匹配的URL)「原始」的字符串在Haskell的正則表達式

\b(((\S+)?)(@|mailto\:|(news|(ht|f)tp(s?))\://)\S+)\b 

爲正則表達式,但問題是我一直在ghci中

Prelude Text.RegExp> let a = fromString "\b(((\S+)?)(@|mailto\:|(news|(ht|f)tp(s?))\://)\S+)\b" 

<interactive>:1:27: 
    lexical error in string/character literal at character 'S' 

我猜它的失敗,因爲Haskell的不理解\S作爲轉義代碼收到此錯誤。有什麼辦法可以解決這個問題嗎?

在Scala中,你可以用3個雙引號括住一個字符串,我想知道你是否可以在Haskell中實現類似的東西?

任何幫助,將不勝感激。

+1

根據http://stackoverflow.com/questions/3792267/haskell-do-literal-backslas-always-have-to-be-escaped-in-a-string haskell找到的答案haskell沒有任何語法原始的字符串,所以你必須像@augustss所說的那樣逃避每個反斜槓。 – 2011-05-25 10:24:41

+0

..我相信你必須使用pcre-light或regex-pcre來獲得一個知道\ S的實現。除了perl-like引擎外,還有類似posix的引擎,例如regex-tdfa(不能識別\ s)。 – 2011-05-25 11:15:33

回答

12

字符串中的每個反斜槓都必須在雙引號內寫爲雙反斜槓。所以

"\\b(((\\S+)?)(@|mailto\\:|(news|(ht|f)tp(s?))\\://)\\S+)\\b" 

更一般的評論:你最好寫一個適當的分析器,而不是使用正則表達式。正則表達式很少做正確的事情。

+0

...嗯 - 但:正則表達式應該快得多。爲類型3語言編寫LR或LL解析器不應該是一個有效的解決方案。 – phynfo 2011-05-25 10:41:48

+0

@phynfo,但是,解析器將允許您組合使用模式並輕鬆地從解析中提取信息。速度不是一切。 – luqui 2011-05-25 11:47:09

+0

@phyinfo如果速度是最重要的,我會使用一個簡單的正則表達式來識別有效URL的超集,然後使用真正的解析器來驗證它們。 – augustss 2011-05-25 11:56:50

4

哈斯克爾不支持原始字符串開箱即用的,然而,在GHC它很容易使用quasiquotation實現它們:

r :: QuasiQuoter 
r = QuasiQuoter {  
    quoteExp = return . LitE . StringL 
    ... 
} 

用法:

ghci> :set -XQuasiQuotes 
ghci> let s = [r|\b(((\S+)?)(@|mailto\:|(news|(ht|f)tp(s?))\://)\S+)\b|] 
ghci> s 
"\\b(((\\S+)?)(@|mailto\\:|(news|(ht|f)tp(s?))\\://)\\S+)\\b" 

我已經發布了此代碼的稍微擴展和文檔化版本爲Hackage上的raw-strings-qq庫。