字符串解析和人类正则表达式

sparser的Python项目详细描述


sparser是字符串解析和正则表达式,对于人类来说,解析字符串是一项非常困难的任务。当处理多行字符串时,这个困难会成倍增加。传统上,正则
表达式用于此。然而,任何使用过正则表达式的人都知道,这些表达式很难阅读,很难维护,充满了问题,并且不能在多行上很好地扩展。
sparser就是为解决这个问题而开发的。

&g t;>;将sparser导入为sp
>;>t;pattern="你好{{str}!"
>>>string="你好,世界!"
>;>;r=sp.match(pattern,string)
>;>;打印r
true

>;>;pattern="您好{{str planet}!"
>>>string="你好,世界!"
>;>;r=sp.match(pattern,string)
>;>;打印r
true

>;>;pattern="您好{{str planet}!"
>>>string="你好,世界!"
>;>;r=sp.parse(pattern,string)
>;>;print r
{'planet':'world'}


从语法上讲,sparser是[正则表达式](https://docs.python.org/2/library/re.html)和[把手](https://github.com/wycats/handlebars.js/)样式模板的组合。更精确的标记行可能是,*sparser是一种用于匹配和分析字符串的反向模板语言*

>;>pattern="在{int hour}:{int minute}"\
关闭{{spstr rocket}{str}},并花费{currency price}。"
>;>compiled=sp.compile(pattern)
>;>print compiled.parse("猎鹰9号5:30起飞,耗资6200万美元。")
{rocket':"猎鹰9号","小时":5,
"分钟":30,
"价格":6200万



[示例](示例)
2.[安装](安装)
3.[文件](文件)
1.[方法参考](方法参考)
2.[模式行为](模式行为)
3.[标签](标签)
4.[内置类型](内置类型)
5.[自定义类型](自定义类型)
4.[待办事项](待办事项)
5.[类似项目](类似项目)
6.[错误](错误)



}{sp str food}"{br/>"在{str month}{rd的{int date}"上"
>;{custom_types={"animal":("cat_dog_pig",none)}
>;>compiled=sp.compile(patt,custom_types)
>;>print compiled.parse("英俊的猫在23号的时候喝得酩酊大醉"七月日")
{'who':'cat',
'action':'slurping',
'food':'pho',
'date':23,
'month':'july}

'tuple中的第一个参数是要匹配的regex。第二个
是回调方法。如果要清除输出,请使用它。

>;>;自定义类型={"动物":("猫狗猪",str.upper)}
>;>;>;已编译=sp.compile(patt,自定义类型)
>;>;打印已编译。parse("7月23日漂亮的猫在舔pho")
{"谁":猫猫,
'action':'slurping',
'food':'pho',
'date''date''23,
'month''month''七月}




>对于简单的一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性一次性br/>"在{int date}{{"st{nd{rd}of{str month}"
>;>;compiled=sp.compile(patt)
>;>;>;print compiled.parse("漂亮的猫在7月23日喝得酩酊大醉")
{who':'cat,
'action':'slurping',
'food':'pho',
'date':23,
'month':'july'}


循环是sparser最强大的功能之一。对于格式简单的表


>;>;patt="\
{*loop imdb_list*}
{*case*}{{{int rank},它们是很好的选择。{{spstr title}({{int year})+{{float rating}{*endcase*}
{*endloop*}"
>>gt;compiled=sp.compile(patt)
>>gt;imdb_top_250="
1。肖申克的救赎(1994)9.2
2。教父(1972)9.2
3.教父:第二部分(1974)9.0
4。《黑暗骑士》(2008)8.9"
>;>;print compiled.parse(imbd_top_250)
{《imdb_list》:[
{《rating》:9.2,"year":1994,"rank":1,"title":《肖申克救赎》},
{《rating》:9.2,"year":1972,"rank":2,"title":《教父》},
《rating》:9.0,"年份":1974,"等级":3,"标题":"教父:第二部分"},
{"等级":8.9,"年份":2008,"等级":4,"标题":"黑暗骑士"}
]}


s*}
{*case header*}{{spalpha name}{*endcase*}
{*case line{item*}{{spalpha name}{{{currency price}{*endcase*}
{*case total*}total{{{spalpha name}}:{{currency price}{*endcase*}
{*case break*}{*endcase*}
{*endloop*}
净收入{货币净收入}"
>>compiled=sp.compile(patt)
>>费用
销货成本$15
折旧$3
工资$30
总费用:$28

ems":[
{"case":"header","name":"revenues"},
{"case":"line廑item","price":30.0",name":"商品销售"},
{"case":"line廑item","price":8.0",name":"其他收入"},
{"case":"total","price":38.0",name":"revenues"},
{"case":"break"},
{"case":"header","name":"expenses"},
{"case":"line庠item","price":15.0,"name":"销货成本"},
{"case":"line庠item","price":3.0,"name":"defication"},
{"case":"line庠item","price":30.0,"name":"wages"},
{"case":"total","pric"e":28.0",name":"expenses"},
{"case":"break"},
"net_income":-10.0}




与循环类似的是交换语句。这些可以用于简单的
多选项匹配

>;>;patt="\
爱国者是{*switch statement*}
{*case fact*}一个NFL团队{*endcase*}
{*case opinion*}高估了{*endcase*}
{*case telling it_like_it_is*}ball deflaters和serial作弊器{*endcase*}
{*endswitch*}。"
>;>compiled=sp.compile(patt)
>;>string="爱国者是通缩球和serial作弊器。"
>;>print compiled.parse(string)
{"statement":{"case":"告诉你"可以使用{\*include<;what>;\*}语句将模式嵌入到模式中。
这在预处理器级别(如从c定义)工作,因此它相当于复制和粘贴。这对于重用常见的
模式或分解和组织较长的模式很有用。

>;>;patt="
{*循环日志*}
{*案例*}{*包括ISO8601*}:{{{spstr error}{*endcase*}
{*case*}{{spstr error}:{*include ISO8601*}{*endcase*}"{{int-ye年{{{int-ye年}{{{{{int-月}{{{{{{int-ye年}{{{{{int-月}{{{{int-day}{{{{{{{{{{{int-小时}{{{{{{{int分钟}{{{{float第二}}}"""
>>>;gt>logs=""
>assertorror:2017-03-min分分钟}}{{{{{{{{{int-float第二}}}}}}"
br/>>>>>>;loggt;logs=>assertertert04t21:49:20。932833
2017-03-04t21:52:03.987341:typeerror
"
>;>;compiled=sp.compile(patt,includes={"iso8601":iso8601})
>;>;打印compiled.parse(logs)
{logs':[
{error':"assertionerror",
"day":4,
"hour":21,
"分钟":40,
"月":3,
"秒":43.408923,
"年":2017},
{"错误":零分区错误,
"日":4,
"小时":21,
"分钟":49,
"月":3,
"秒":20.932833,
"年":2017},
{'error':'typeerror',
'day':4,
'hour':21,
'minute':52,
'month':3,
'second':3.987341,
'year':2017}
]}


不幸的是,sparser不支持v0.1中的嵌套开关和循环。这可能会在以后的版本中更新




installation
==


$pip install sparser





字符串并返回字典。
如果字符串与模式不匹配,则会引发sparservalueerror异常
。可选地,使用自定义类型({type_name:(type_pattern,callback)}格式)
和/或includes({include_name:pattern})<;/p>;

**sparser.match**(pattern,string[,custom_types[,includes]])

<;p>;与parse相同,但不返回字典,如果e
模式成功匹配字符串。在内部,这与
sparser.parse的工作原理相同,但当您只需要知道某个内容是否匹配
,并且不想处理错误处理或错误的空字典时,它很有用。<;/p>;

**sparser.compile**((pattern[,custom_types[,includes]])

<;p>;pre com堆一个模式并返回一个sparserobject,稍后可以调用parse/match
on。如果速度是必需的,或者只是为了保持代码干净,则这非常有用。<;/p>;

**sparserobject.parse**(string[,custom_types[,includes]])

<;p>;与sparser.parse相同,但使用sparser.compile方法预编译[,custom_types[,includes]])

<;p>;与sparser.match相同,但使用sparser.compile方法进行预编译<;/p>;



pattern behavior
----
sparser需要完全匹配,而不会进行部分匹配。这意味着打印sp.parse("你好{{alpha planet},很高兴认识你","你好,世界,很高兴认识你")
{planet':"世界"}

,但这会引起sparservalueerrors

>;>;打印sp.parse("你好{alpha planet}","Hello World,很高兴见到你")
sparservalueerror
>;>print sp.parse("你好{alpha planet},很高兴见到你","你好世界")
sparservalueerror
>;>print sp.parse("你好{alpha planet}","你好世界")
sparservalueerror

然后,您可以在模式前或模式后使用{{spstr}`标记
,就像这样

>>;>print sp.parse("你好{{alpha planet}}{spstr}","你好,很高兴见到你")
{planet':'world}
>;>}{{spstr},"hello world")
{planet':'world'}
>;>print sp.parse({spstr}}hello{{alpha planet},"blah blah hello world")
{planet':'world'}

`spstr'是一种内置类型,表示"间隔字符串"。这相当于
regex`.+`表示"任何字符1+次"。




如果在
开关/循环内没有匹配的情况,它将引发sparservalueerror



所以,如果你有一张这样的桌子,

winners
1。桃子
2.Yoshi
3.再弹一遍?

下面的模式将引发sparservalueerror,因为它将尝试再次"匹配"播放?`在循环中。

{*循环排名的玩家}
{*case*}{{{int rank}。{{str name}{*endcase*}
{*endloop*}



{{str name}{*endcase*}
{*endloop*}
重新播放?

或者,一个{{spstr}可以在紧要关头工作


{winners
{loop-randed}
{case*}{{int-rank}。{{str name}{*endcase*}
{*endloop*}
{{{{spstr}



支持多行循环,但不支持内联循环。
sparser应在0.2版中支持内联循环。同时,您可以在自定义或lambda
类型中使用regex bar(` `)运算符。




这意味着sp.match("月亮","月亮")

线。这并非没有先例。html
呈现的工作方式相同。这是因为在解析多行正则表达式时存在着独特的挑战。




tags
----
目前,sparser中只有8个标记

---------------
{{<;var_type>;{\*switch<;switch_name>;\*}只能包含{\*case\*}标记作为直接的分散项
{\*endswitch\*}只包含{\*case\*}标记作为直接分散项
{\*endloop\*}
{\*case<;case_name>;\*}case_name是可选的
{\*endcase\*}
{include<;include_name>;\*}这只会将一种模式插入另一种模式。把它想象成C的"define"宏




--—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————不接受小数"-"??[0-9,]+"
浮点浮点"-??[0-9,.]+"
阿尔法|无数字、特殊字符或空格的字符串"[a-za-z]+"
spalpha无数字或特殊字符的字符串"[a-za-z]+"
字母数字无特殊字符或空格的字符串"[a-za-z0-9]+"
spalphanumeric无特殊字符的字符串|"[a-za-z0-9]+"
currency一个可以前缀为"$"和/或"-"的浮点数-??[$-]*[0-9,.]+"




自定义类型
----
自定义类型是可选参数。它们的形式是

{type_name:(regex_pattern,callback),…}


callback是一个函数,用于在将提取的字符串包含在
字典中之前修改它。例如,要将匹配大写,请执行

str.upper也可以工作


如果要添加自定义日期类型,可以执行类似于

date cb=lambda dt廑str:date.strptime(st廑str,"%m/%d/%y")的操作
custom types={"date":("\d{2}/\d{2}/\d{4},date_cb)}


如果您只想返回未修改的字符串,请传入"none"


custom_types={"berry":("(?:blue black rasp)berry",none)}



==
-嵌套循环(需要将主要部分重写为有限状态机)
-内联循环(如果循环两边不相邻,则不应自动换行)
-清理ast的构建nicode兼容货币(欧元、日元等)
-测试应使用assertraiseregexp并与引发的异常完全匹配
-内置日期类型
-。搜索不严格匹配





类似项目
===
-[分析](https://pypi.python.org/pypi/parse)
-[pyparsing](http://pyparsing.wikispaces.com/)



bugs
==
这是0.1版,可能有一两个我们遗漏的bug。请通知我们或提交修补程序。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
带有嵌套JAR的java RCP ClassNotFoundException   java在输入框中设置默认值,crud应用程序使用spring   java如何在Heroku中使用fs创建新文件   java将JPanel放在JFrame中   java这个正则表达式会匹配“i.imgur.com/xxx”吗?   java在片段内创建RecylerView,而无需在Android中设置片段   Android上Groovy导致java错误的双精度浮点精度损失   swing Java查找JFrame属于JPanel的内容   java Spring junit自连线自定义类本身必须有构造函数吗?   java textswitcher支持前面的文本   从Android客户端到JAXRS的java Post自定义对象   java如何检索JSON数据并使用MPAndroidChart绘制折线图,以及在安卓上的改进   拒绝用户“root”@“localhost”的java c3p0访问(使用密码“是”)   使用Selenium Webdriver自动化ExtJS应用程序时java面临的问题