区分Haskell中的空regexp匹配项和无匹配项

区分Haskell中的空regexp匹配项和无匹配项,regex,haskell,pcre,Regex,Haskell,Pcre,我正在尝试使用regex pcre,但是regex base包含了太多的RegexContext重载,因此我不知道手头的任务应该使用哪个重载 我希望通过以下方式将字符串与(foo)-(bar)|(qux)-(qux)(q*u*u*x*)正则表达式匹配: myMatch :: String -> Maybe (String, String, Maybe String) 样本输出: myMatch“dfjdjk”应该是Nothing,因为没有匹配项 myMatch“foo-bar”应该是J

我正在尝试使用
regex pcre
,但是
regex base
包含了太多的
RegexContext
重载,因此我不知道手头的任务应该使用哪个重载

我希望通过以下方式将字符串与
(foo)-(bar)|(qux)-(qux)(q*u*u*x*)
正则表达式匹配:

myMatch :: String -> Maybe (String, String, Maybe String)
样本输出:

  • myMatch“dfjdjk”
    应该是
    Nothing
    ,因为没有匹配项

  • myMatch“foo-bar”
    应该是
    Just(“foo”,“bar”,Nothing)
    ,因为在第一个备选方案中没有第三个捕获组

  • myMatch“quux quuxqu”
    应该是
    Just(“quux”,“quux”,Just“qu”)

  • myMatch“qux-qux”
    应该是
    Just(“qux”,“qux”,Just”)
    ,因为第三个捕获组存在但为空


这不是一个任务,我只是困惑于在没有匹配或没有捕获组的情况下如何不包含代码路径

实现它的一种方法是使用
getAllTextSubmatches

import Text.Regex.PCRE

myMatch :: String -> Maybe (String, String, Maybe String)
myMatch str = case getAllTextSubmatches $ str =~ "(foo)-(bar)|(quux)-(quux)(q*u*u*x*)" :: [String] of
  []                      -> Nothing
  [_, g1, g2, "", "", ""] -> Just (g1, g2, Nothing)
  [_, "", "", g3, g4, g5] -> Just (g3, g4, Just g5)
getAllTextSubmatches
[String]
作为返回类型时,如果没有匹配项,它将返回一个空列表,或者返回一个包含第一个匹配项的所有捕获组(其中索引0是整个匹配项)的列表

或者,如果匹配的组可能为空,并且无法对空字符串进行模式匹配,则可以使用
[(string,(MatchOffset,MatchLength))]
作为
getAllTextSubmatches
的返回类型,并使用-1进行模式匹配
MatchOffset
来标识不匹配的组:

myMatch :: String -> Maybe (String, String, Maybe String)
myMatch str = case getAllTextSubmatches $ str =~ "(foo)-(bar)|(quux)-(quux)(q*u*u*x*)" :: [(String, (MatchOffset, MatchLength))] of
  []                                                              -> Nothing
  [_, (g1, _), (g2, _), (_, (-1, _)), (_, (-1, _)), (_, (-1, _))] -> Just (g1, g2, Nothing)
  [_, (_, (-1, _)), (_, (-1, _)), (g3, _), (g4, _), (g5, _)]      -> Just (g3, g4, Just g5)
现在,如果这看起来太冗长:

{-# LANGUAGE PatternSynonyms #-}

pattern NoMatch = ("", (-1, 0))

myMatch :: String -> Maybe (String, String, Maybe String)
myMatch str = case getAllTextSubmatches $ str =~ "(foo)-(bar)|(quux)-(quux)(q*u*u*x*)" :: [(String, (MatchOffset, MatchLength))] of
  []                                               -> Nothing
  [_, (g1, _), (g2, _), NoMatch, NoMatch, NoMatch] -> Just (g1, g2, Nothing)
  [_, NoMatch, NoMatch, (g3, _), (g4, _), (g5, _)] -> Just (g3, g4, Just g5)

要区分何时没有匹配,请使用,以便将结果放入
Maybe
单子中。如果没有匹配项,它将使用
fail
返回
Nothing

myMatch :: String -> Maybe (String, String, Maybe String)
myMatch str = do
    let regex = "(foo)-(bar)|(quux)-(quux)(q*u*u*x*)"
    groups <- getAllTextSubmatches <$> str =~~ regex :: Maybe [String]
    case groups of
        [_, g1, g2, "", "", ""] -> Just (g1, g2, Nothing)
        [_, "", "", g3, g4, g5] -> Just (g3, g4, Just g5)
myMatch::String->Maybe(String,String,Maybe String)
myMatch str=do
let regex=“(foo)-(bar)|(qux)-(qux)(q*u*u*x*)”
组(g1、g2、无)
只是(g3,g4,g5)

使用
regex applicative

myMatch = match re
re = foobar <|> quuces where
    foobar = (,,) <$> "foo" <* "-" <*> "bar" <*> pure Nothing
    quuces = (,,)
        <$> "quux" <* "-"
        <*> "quux"
        <*> (fmap (Just . mconcat) . sequenceA)
            [many $ sym 'q', many $ sym 'u', many $ sym 'u', many $ sym 'x']
myMatch=match-re
re=foobar quuces在哪里

foobar=(,,“foo”你需要锚定:这取决于我想要什么:)我想要
“fdoifoo bardjfkj”
也被匹配:)我可能不明白,但你的表达式是按照你描述的方式工作的:用以将
目标
包装在单子中,比如
可能
@4castle,你能把你的评论作为答案吗?在
foobarfoobar
上会失败吗?我只需要比赛一次。模式匹配在
mrSubList x=~~(foo)-(bar)|(qux)-(qux)(q*u*u*x*)“
上更好吗?@nponeccop应该只给出第一个匹配。我还没有实际测试我的代码,所以我可能需要编辑它,但希望这能证明我的想法。不幸的是,这不起作用:列表总是6个元素长,不匹配的捕获都是
。下面是一个简短的说明:
(*)foo |(*)bar
。在Perl中,
$1
$2
'
未定义的
,因此可以将不匹配的捕获组与匹配但为空的捕获组区分开来。@nponeccop我的系统现在正在使用它。我使用的是
regex-pcre-builtin
。我希望它能够更好地区分不匹配的捕获组,但在这种情况下,
将起作用。然后我可以编写一个包装器,用
向不匹配的组发送信号。干得好
re = foobar <|> quuces where
    foobar = do
        foo <- "foo"
        _ <- "-"
        bar <- "bar"
        pure (foo, bar, Nothing)
    quuces = do
        quux1 <- "quux"
        _ <- "-"
        quux2 <- "quux"
        quux3 <- fmap snd . withMatched $
            traverse (many . sym) ("quux" :: [Char])
            -- [many $ sym 'q', many $ sym 'u', many $ sym 'u', many $ sym 'x']
        pure (quux1, quux2, Just quux3)