2011-05-25 16 views
5

Me parece estar teniendo problemas para crear una expresión regular en Haskell, lo que estoy tratando de hacer es convertir esta cadena (que coincide con una URL en un trozo de texto)"crudo" cadena en Haskell para la expresión regular

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

en una expresión regular, el problema es que siguen dando este error en 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' 

supongo que está fallando debido a Haskell no entiende \S como un código de escape. ¿Hay alguna forma de evitar esto?

En Scala puede rodear una cadena con 3 comillas dobles, me preguntaba si podría lograr algo similar en Haskell.

Cualquier ayuda sería apreciada.

+1

según las respuestas encontradas en http://stackoverflow.com/questions/3792267/haskell-do-literal-backslashes-todo-algo-que-tiene-en-escalado-en-una-cadena Haskell no tiene ninguna sintaxis para cadenas crudas por lo que debe escapar de cada barra invertida, como dijo @augustss. –

+0

... y creo que debes usar pcre-light o regex-pcre para obtener una implementación que sepa de \ S. Además de los motores similares a Perl, hay motores similares a posix como regex-tdfa (que no reconoce \ s). –

Respuesta

12

Cada barra invertida en su cadena debe escribirse como una doble barra invertida dentro de las comillas dobles. Así

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

Una observación más general: que sería mejor escribir un analizador adecuado en lugar de utilizar expresiones regulares. Las expresiones regulares rara vez hacen exactamente lo correcto.

+0

... hmm - pero: las expresiones regulares deberían ser mucho más rápidas. Escribir un analizador LR o LL para un lenguaje de tipo 3 no debería ser una solución eficiente. – phynfo

+0

@phynfo, sin embargo, un analizador le permitirá usar patrones de forma comprable y extraer fácilmente información del análisis. La velocidad no es todo. – luqui

+0

@phyinfo Si la velocidad es de suma importancia, usaría una expresión regular simple que reconozca un superconjunto de las URL válidas y luego use un analizador real para verificarlas. – augustss

4

Haskell no admite cuerdas primas fuera de la caja, sin embargo, en GHC es muy fácil de implementar usando quasiquotation:

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

Uso:

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" 

me ha salido una Versión un poco más expandida y documentada de este código como la biblioteca raw-strings-qq en Hackage.

1

Soy un gran fan de la biblioteca Rex:

http://hackage.haskell.org/package/rex

http://hackage.haskell.org/packages/archive/rex/0.4.2/doc/html/Text-Regex-PCRE-Rex.html

cual no sólo utiliza quasiquoting para la entrada de expresiones regulares agradable (no hay barras invertidas dobles), también se utiliza como las de Perl expresiones regulares y no las molestas expresiones regulares POSIX molestas, e incluso le permite usar expresiones regulares como patrones que coincidan con los parámetros de su método, lo cual es genio.

Cuestiones relacionadas