替换-解析
![堆叠LTS](http://stackage.org/package/replace-attoparsec/badge/lts)
替换-解析用于查找文本模式,而且替换或拆分找到的模式。此活动传统上是使用正则表达式完成的,但是替换-解析使用阿托帕塞克用于模式匹配的解析器。
替换-解析可以用于相同类型的“模式捕获”或使用Python的“查找所有”情况雷·芬达尔
或波尔米//
,或Unix公司格雷普
.
替换-解析可用于相同类型的“流编辑”或使用Python的“搜索和替换”情况re.sub
,或波尔秒///
,或Unix塞德
,或awk公司
.
替换-解析可用于相同类型的“字符串拆分”使用Python的情况重新拆分
或Perl分裂
.
请参见替换-megaarsec对于百万帕斯卡版本。
为什么我们要用解析器而不是正则表达式来进行模式匹配和替换?
-
Haskell解析器的语法比正则表达式,这是出了名的难以阅读.
-
正则表达式可以对匹配的模式,但它们只能返回捕获组的字符串列表。分析器可以基于捕获组构造类型化数据结构,确保模式规则和我们使用的规则之间没有分歧根据模式匹配构建数据结构。
例如,考虑扫描字符串中的数字。很多不同的东西看起来像一个数字,可以有前导加号或减号,也可以用科学符号表示,或者有逗号之类的。如果我们试图从字符串中解析所有数字使用正则表达式,则必须确保正则表达式字符串到数字的转换函数与以及什么不是数字字符串。我们可能会陷入尴尬的境地正则表达式表示它找到了一个数字字符串,但字符串到数字的转换功能失败。类型化解析器将执行这两项操作模式匹配和转换,因此永远不会出现这种情况。解析,而不是验证。
-
正则表达式只能进行模式匹配有规律的克。Attoparsec解析器能够与无上下文语法进行模式匹配。
-
基于传统正则表达式的替换表达式替换命令通常只是一个字符串模板,其中这个第N个可以使用语法插入“捕获组”\N个
。使用这个库,而不是模板,我们得到一个编辑
可以执行任何计算(包括IO)的函数。
使用示例
尝试中的示例全球温室气体排放指数
通过运行电缆v2-repl
在中替换attoparsec/
根目录。
示例取决于这些导入和LANGUAGE重载字符串
.
:set-XOverloadedStrings导入替换。Attoparsec公司。文本导入数据。Attoparsec公司。文本为AT导入合格数据。文本为T进口管制。适用导入数据。要么导入数据。烧焦
使用拆分字符串拆分Cap
查找所有模式匹配项,捕获匹配的文本和解析的结果
将输入字符串分隔成可以解析为十六进制的部分带前缀的数字“0x”
,和不能的部分。分析数字。
让hexparser=string“0x”*>十六进制::Parser整数splitCap(匹配十六进制分析器)“0xA 000 0xFFFF”
[右(“0xA”,10),左“000”,右(“xFFFF”,65535)]
模式匹配平衡括号
查找平衡嵌套括号组。这是一个“上下文无关”语法,一种不能用正则表达式表示的模式表达式。我们可以用递归解析器表示模式。
导入数据。Functor(无效)导入数据。双函子(秒)let parens:Parser()parens=做字符“(”直到(无效parens<|>void anyChar)(字符')')纯()第二个fst<$>splitCap(匹配参数)“(())(()())”
[右“()”、左“”、右“(()())”]
使用编辑文本字符串stream编辑
以下示例显示了如何搜索文本字符串中的模式然后编辑文本字符串以替换某些替换文本用于匹配的模式。
模式匹配并替换为常量
用换行符替换所有车厢换行符。
streamEdit(字符串“\r\n”)(常量“\n”)“1\r\n2\r\n”
“1\n2\n”
模式匹配并编辑匹配项
将字母字符替换为字母表中的下一个字符。
流编辑(AT.takeWhile isLetter)(T.map suc)“HAL 9000”
“IBM 9000”
模式匹配,可能编辑匹配,也可能不去管它们
查找所有字符串部分秒
可以解析为十六进制数第页
,如果r≤16
,然后更换秒
带有十进制数。使用比赛
组合器。
让hexparser=string“0x”*>十六进制::Parser整数streamEdit(匹配十六进制分析器)(\(s,r)->如果r<=16,则T.pack(show r)else s)“0xA 000 0xFFFF”
“10 000 0xFFFF”
模式匹配并使用IO编辑匹配流编辑T
在花括号中查找环境变量并将其替换为来自环境的价值。
导入系统。环境(getEnv)streamEditT(char'{'*>manyTill-anyChar(char'}'))(fmap T.pack.getEnv)“-{HOME}-”
“-/home/jbrock-”
模式匹配,编辑匹配,并使用计数编辑流编辑T
查找字符串中不超过三个字母并将其大写,然后返回编辑字符串以及大写字母的数量。要启用编辑器功能可以记住它大写了多少个字母,我们将运行流编辑T
在中州
来自的单子mtl公司
包裹。使用这个获得与Python相同功能的技术re.subn公司
.
导入合格的控件。莫纳德。州。与MTL一样严格进口管制。莫纳德。州。严格(get、put、runState)导入数据。字符(到上)让编辑三::字符->MTL。状态Int T.文本editThree x=执行我<-得到如果i<3然后做放$i+1纯$T.singleton$toUpper x其他纯$T.singleton xflip runState 0$streamEditT(满足isLetter)editThree“a a a a”
(“A A A A A A”,3)
在壳牌公司
如果我们要有一个可行的塞德
更换,然后我们希望能够从命令行轻松使用它。这个堆栈脚本解释器该脚本将在流中查找十进制数,并将其替换为双精度数。
#!/usr/bin/env堆栈{-堆栈脚本--分解器lts-16--包裹attoparsec--程序包文本--软件包文本显示--包替换-访问解析-}--https://docs.haskellstack.org/en/stable/GUIDE/#script-口译员{-#LANGUAGE重载字符串#-}导入合格数据。文本为T导入合格数据。文本。IO作为T导入TextShow导入数据。Attoparsec公司。文本导入替换。Attoparsec公司。文本main=T.interactive$streamEdit十进制(showt.(*(2::Integer))
如果你有Haskell工具组安装后,您可以将其复制到名为双重r.hs
和运行它。(第一次运行时,Stack可能需要下载依赖项。)
$chmod u+x倍r.hs$echo“1 6 21 107”|/双重r.hs2 12 42 214
选择
人们可能会考虑用一些库来代替这个库。
http://hackage.haskell.org/package/regex-applicative网站
http://hackage.haskell.org/package/pcre-heavy
http://hackage.haskell.org/package/lens-regex-pcre
http://hackage.haskell.org/package/regex
http://hackage.haskell.org/package/pipes-parse
http://hackage.haskell.org/package/stringsearch
http://hackage.haskell.org/package/substring解析器
http://hackage.haskell.org/package/pcre-utils
http://hackage.haskell.org/package/template
https://github.com/RaminHAL9001/parser-sed-thing
http://hackage.haskell.org/package/attosplit
基准
这些基准旨在测量墙锁速度属于除了实际的图案匹配之外的一切。的速度图案匹配是百万帕斯卡和阿托帕塞克库。
基准任务是找到所有的单字符模式x个
在一个文本流并将其替换为返回常量的函数一串面向对象
。所以,就像正则表达式一样s/x/oo/g
.
我们有两个基准输入案例,我们称之为稠密的和稀疏的.
这个稠密的大小写是1兆字节的交替空格和x个
秒喜欢
x x x x x x x x xx x x×x x x
这个稀疏的大小写是一个兆字节的空格x个
在中间喜欢
x个
每个基准程序从标准输入
,替换x个
具有哦
,并将结果写入标准输出
。所用时间的测量方法为性能统计
,记录了最佳观测时间。
请参见更换基准点了解详细信息。
假设性问题
-
我们可以为编写这个库吗解析?
不,因为比赛
组合符不存在于解析(我哪儿也找不到。它能写吗?)
-
这是个好主意吗?
你可能有听说有人建议一元解析器更适合模式匹配输入流主要是信号流,正则表达式更好当输入流主要是噪声时。
这个库的前提是一元解析器非常适合查找杂乱文本流中的小信号模式。
我们不愿放弃通过限制提供的加速机会我们对常规语法的迷信由来已久机会,其中仍然大部分未开发.允许堆栈内存分配(也称为下推)的性能折衷自动机,也称为上下文无关语法)有争议的通用的程序设计语言.我想我们现在可以用与模式匹配语言相同的方式解决这个争议。