Регистрозависимые регулярные выражения
Каков наилучший способ использовать регулярные выражения с параметрами (флагами) в Haskell?
я использую
Text.Regex.PCRE
В документации перечислены несколько интересных опций, таких как compCaseless, compUTF8, ... Но я не знаю, как их использовать с (=~)
3 ответа
Все Text.Regex.*
Модули интенсивно используют классы типов, которые предназначены для расширяемости и поведения, подобного "перегрузке", но делают использование менее очевидным из простого просмотра типов.
Теперь вы, вероятно, начали с основного =~
согласовани.
(=~) ::
( RegexMaker Regex CompOption ExecOption source
, RegexContext Regex source1 target )
=> source1 -> source -> target
(=~~) ::
( RegexMaker Regex CompOption ExecOption source
, RegexContext Regex source1 target, Monad m )
=> source1 -> source -> m target
Использовать =~
должен существовать экземпляр RegexMaker ...
для LHS, и RegexContext ...
для RHS и результата.
class RegexOptions regex compOpt execOpt | ...
| regex -> compOpt execOpt
, compOpt -> regex execOpt
, execOpt -> regex compOpt
class RegexOptions regex compOpt execOpt
=> RegexMaker regex compOpt execOpt source
| regex -> compOpt execOpt
, compOpt -> regex execOpt
, execOpt -> regex compOpt
where
makeRegex :: source -> regex
makeRegexOpts :: compOpt -> execOpt -> source -> regex
Допустимый экземпляр всех этих классов (например, regex=Regex
, compOpt=CompOption
, execOpt=ExecOption
, а также source=String
) означает, что можно скомпилировать regex
с compOpt,execOpt
варианты из какой-то формы source
, (Также, учитывая некоторые regex
типа, там ровно один compOpt,execOpt
набор, который идет вместе с ним. Много разных source
Типы в порядке, хотя.)
class Extract source
class Extract source
=> RegexLike regex source
class RegexLike regex source
=> RegexContext regex source target
where
match :: regex -> source -> target
matchM :: Monad m => regex -> source -> m target
Допустимый экземпляр всех этих классов (например, regex=Regex
, source=String
, target=Bool
) означает, что можно сопоставить source
и regex
дать target
, (Другое действует target
с учетом этих конкретных regex
а также source
являются Int
, MatchResult String
, MatchArray
, так далее.)
Положите их вместе, и это довольно очевидно, что =~
а также =~~
просто удобные функции
source1 =~ source
= match (makeRegex source) source1
source1 =~~ source
= matchM (makeRegex source) source1
а также что =~
а также =~~
не оставляйте места для передачи различных вариантов makeRegexOpts
,
Вы могли бы сделать свой собственный
(=~+) ::
( RegexMaker regex compOpt execOpt source
, RegexContext regex source1 target )
=> source1 -> (source, compOpt, execOpt) -> target
source1 =~+ (source, compOpt, execOpt)
= match (makeRegexOpts compOpt execOpt source) source1
(=~~+) ::
( RegexMaker regex compOpt execOpt source
, RegexContext regex source1 target, Monad m )
=> source1 -> (source, compOpt, execOpt) -> m target
source1 =~~+ (source, compOpt, execOpt)
= matchM (makeRegexOpts compOpt execOpt source) source1
который может быть использован как
"string" =~+ ("regex", CompCaseless + compUTF8, execBlank) :: Bool
или перезаписать =~
а также =~~
с методами, которые могут принимать параметры
import Text.Regex.PCRE hiding ((=~), (=~~))
class RegexSourceLike regex source
where
makeRegexWith source :: source -> regex
instance RegexMaker regex compOpt execOpt source
=> RegexSourceLike regex source
where
makeRegexWith = makeRegex
instance RegexMaker regex compOpt execOpt source
=> RegexSourceLike regex (source, compOpt, execOpt)
where
makeRegexWith (source, compOpt, execOpt)
= makeRegexOpts compOpt execOpt source
source1 =~ source
= match (makeRegexWith source) source1
source1 =~~ source
= matchM (makeRegexWith source) source1
или вы могли бы просто использовать match
, makeRegexOpts
и т. д. непосредственно там, где это необходимо.
Я ничего не знаю о Haskell, но если вы используете библиотеку регулярных выражений на основе PCRE, то вы можете использовать модификаторы режима внутри регулярного выражения. Чтобы сопоставить регистр без учета регистра, вы можете использовать это регулярное выражение в PCRE:
(?i)caseless
Модификатор режима (? I) переопределяет любой параметр чувствительности к регистру или нечувствительности к регистру, который был установлен вне регулярного выражения. Он также работает с операторами, которые не позволяют вам устанавливать какие-либо параметры.
Точно так же (? S) включает "однострочный режим", который приводит к разрыву строки при совпадении точек, (? M) включает "многострочный режим", который делает совпадения ^ и $ при разрыве строки, и (? X) включается свободно -spacing mode (неэкранированные пробелы и разрывы строк вне классов символов незначительны). Вы можете комбинировать буквы. (? ismx) включает все. Дефис отключает опции. (?-i) делает регулярное выражение чувствительным к регистру. (?xi) запускает регулярное выражение, чувствительное к регистру.
Я считаю, что не могу использовать (=~), если вы хотите использовать compOpt
Кроме как defaultCompOpt
,
Что-то вроде этой работы:
match (makeRegexOpts compCaseless defaultExecOpt "(Foo)" :: Regex) "foo" :: Bool
Следующие две статьи должны помочь вам: