【发布时间】:2011-04-08 15:04:23
【问题描述】:
如何在 Haskell 中使用正则表达式提取字符串?
let x = "xyz abc" =~ "(\\w+) \\w+" :: String
这没有匹配到
let x = "xyz abc" =~ "(.*) .*" :: String
确实如此,但 x 最终为“xyz abc”如何仅提取第一个正则表达式组以使 x 为“xyz”?
【问题讨论】:
如何在 Haskell 中使用正则表达式提取字符串?
let x = "xyz abc" =~ "(\\w+) \\w+" :: String
这没有匹配到
let x = "xyz abc" =~ "(.*) .*" :: String
确实如此,但 x 最终为“xyz abc”如何仅提取第一个正则表达式组以使 x 为“xyz”?
【问题讨论】:
我编写/维护了 regex-base、regex-pcre 和 regex-tdfa 等软件包。
在 regex-base 中,Text.Regex.Base.Context 模块记录了 =~ 使用的大量 RegexContext 实例。这些是在 RegexLike 之上实现的,它提供了调用 matchText 和 matchAllText 的底层方法。
KennyTM 提到的 [[String]] 是 RegexContext 的另一个实例,可能是也可能不是最适合您的实例。一个综合实例是
RegexContext a b (AllTextMatches (Array Int) (MatchText b))
type MatchText source = Array Int (source, (MatchOffset, MatchLength))
可用于为所有内容获取MatchText:
let x :: Array Int (MatchText String)
x = getAllTextMatches $ "xyz abc" =~ "(\\w+) \\w+"
此时 x 是组匹配的 Array Int 匹配的 Array Int。
请注意,“\w”是 Perl 语法,因此您需要 regex-pcre 才能访问它。如果你想要 Unix/Posix 扩展的正则表达式,你应该使用跨平台的 regex-tdfa,并避免使用 regex-posix,因为它会在实现 regex.h 库时遇到每个平台的错误。
请注意,Perl 与 Posix 不只是像“\w”这样的语法问题。他们使用非常不同的算法并且经常返回不同的结果。此外,时间和空间复杂度也大不相同。为了匹配长度为 'n' 的字符串,Perl 样式 (regex-pcre) 的时间可以是 O(exp(n)),而使用 regex-posix 的 Posix 样式的时间总是 O(n)。
【讨论】:
将结果转换为[[String]]。然后你会得到一个匹配列表,每一个都是匹配的文本列表和捕获的子组。
Prelude Text.Regex.PCRE> "xyz abc more text" =~ "(\\w+) \\w+" :: [[String]]
[["xyz abc","xyz"],["more text","more"]]
【讨论】: