正则表达式的所有匹配的索引

时间:2014-02-06 05:15:57

标签: regex haskell

我试图匹配正则表达式的所有出现并获得索引作为结果。来自 Real World Haskell 的例子说我能做到

string =~ regex :: [(Int, Int)]

但是,自从RWH发布以来,regex库已经更新,因此打破了这个问题。 (参见All matches of regex in Haskell"=~" raise "No instance for (RegexContext Regex [Char] [String])")。这样做的正确方法是什么?

更新

我发现matchAll可能会给我我想要的东西。但我不知道如何使用它。

1 个答案:

答案 0 :(得分:4)

在创建正则表达式时,使用matchAll的关键是使用类型注释:: Regex

import Text.Regex
import Text.Regex.Base

re = makeRegex "[^aeiou]" :: Regex
test = matchAll re "the quick brown fox"

这将返回一个数组列表。要获取(偏移,长度)对的列表,只需访问每个数组的第一个元素:

import Data.Array ((!))

matches = map (!0) $ matchAll re "the quick brown fox"
-- [(0,1),(1,1),(3,1),(4,1),(7,1),(8,1),(9,1),(10,1),(11,1),(13,1),(14,1),(15,1),(16,1),(18,1)]

要使用=~运算符,事情可能会因RWH而发生变化。您应该使用预定义类型MatchOffsetMatchLength以及特殊类型构造函数AllMatches

import Text.Regex.Posix

re = "[^aeiou]"
text = "the quick brown fox"

test1 = text =~ re :: Bool
  -- True

test2 = text =~ re :: String
  -- "t"

test3 = text =~ re :: (MatchOffset,MatchLength)
  -- (0,1)

test4 = text =~ re :: AllMatches [] (MatchOffset, MatchLength)
  -- (not showable)

test4' = getAllMatches $ (text =~ re :: AllMatches [] (MatchOffset, MatchLength))
  -- [(0,1),(1,1),(3,1),(4,1),(7,1),(8,1),(9,1),(10,1),(11,1),(13,1),(14,1),(15,1),(16,1),(18,1)]

有关可用的上下文的更多详细信息,请参阅Text.Regex.Base.Context的文档。

更新:我认为引入了类型构造函数AllMatches来解决当正则表达式具有子表达式时引入的歧义 - 例如:

foo = "axx ayy" =~ "a(.)([^a])"

test1 = getAllMatches $ (foo :: AllMatches [] (MatchOffset, MatchLength))
  -- [(0,3),(3,3)]
  -- returns the locations of "axx" and "ayy" but no subexpression info

test2 = foo :: MatchArray
  -- array (0,2) [(0,(0,3)),(1,(1,1)),(2,(2,1))]
  -- returns only the match with "axx"

两者基本上都是偏移长度对的列表,但它们意味着不同的东西。