热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

lua工具库penlight06数据(二)

词法扫描虽然Lua的字符串模式匹配是非常强大,但需要更强大的东西。pl.lexer.scan可以提供标记字符串,按标记机分类数字、字符串等。lua-l

词法扫描

虽然 Lua 的字符串模式匹配是非常强大,但需要更强大的东西。pl.lexer.scan可以提供标记字符串,按标记机分类数字、字符串等。

 > lua -lpl

 Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio

 > tok = lexer.scan 'alpha = sin(1.5)'

 > = tok()

 iden    alpha

 > = tok()

 =       =

 > = tok()

 iden    sin

 > = tok()

 (       (

 > = tok()

 number  1.5

 > = tok()

 )       )

 > = tok()

 (nil)

 

scanner是一个函数,它会反复被调用并返回标记的类型和值。基本类型有'iden'、 'string'、 'number' 和 'space' ,一切都由基本类型识别。请注意默认情况下扫描程序将跳过任何’space’(空白)标记。

'comment'(注释) 和 'keyword' (关键字)并不是适用于简单的scanner,对所有语言一样,但了解 Lua scanner可以。它承认了 Lua 的关键字,并了解短和长注释和字符串。

 > for t,v in lexer.lua 'for i=1,n do' do print(t,v) end

 keyword for

 iden    i

 =       =

 number  1

 ,       ,

 iden    n

 keyword do

 

词法扫描器会很有用,当没有高度结构化的数据。例如,这里是我维护一个内部文件格式的片段:

 points

 

(818344.1,-20389.7,-0.1),(818337.9,-20389.3,-0.1),(818332.5,-20387.8,-0.1)

 ,(818327.4,–20388,–0.1),(818322,–20387.7,–0.1),(818316.3,–20388.6,–0.1)

 ,(818309.7,–20389.4,–0.1),(818303.5,–20390.6,–0.1),(818295.8,–20388.3,–0.1)

 ,(818290.5,–20386.9,–0.1),(818285.2,–20386.1,–0.1),(818279.3,–20383.6,–0.1)

 ,(818274,–20381.2,–0.1),(818274,–20380.7,–0.1);

 

这是用pl.lexer提取点 :

 -- assume 's' contains the text above...

 local lexer = require 'pl.lexer'

 local expecting = lexer.expecting

 local append = table.insert

 

 local tok = lexer.scan(s)

 

 local points = {}

 local t,v = tok() -- should be 'iden','points'

 

 while t ~= ';' do

     c = {}

     expecting(tok,'(')

     c.x = expecting(tok,'number')

     expecting(tok,',')

     c.y = expecting(tok,'number')

     expecting(tok,',')

     c.z = expecting(tok,'number')

     expecting(tok,')')

     t,v = tok()  -- either ',' or ';'

     append(points,c)

 end

 

expecting函数抓取下一个标记,如果类型不匹配,则会引发一个错误。(pl.lexer ,不同于其他 PL库,如果出了什么差错将引发错误,所以你应该代码中用pcall优雅地捕获错误。)

所有scanner都有第二个可选参数,这是一个表,控制是否您想要排除空白和评论。Lexer.lua的默认值是{space=true,comments=true}。有第三个可选的参数如何处理字符串和数字标记。

高度结构化的数据当然是程序源代码。 ' text-lexer.lua'的一点片段:

 require 'pl'

 

 lines = [[

 for k,v in pairs(t) do

     if type(k) == 'number' then

         print(v) -- array-like case

     else

         print(k,v)

     end

 end

 ]]

 

 ls = List()

 for tp,val in lexer.lua(lines,{space=true,comments=true}) do

     assert(tp ~= 'space' and tp ~= 'comment')

     if tp == 'keyword' then ls:append(val) end

 end

 test.asserteq(ls,List{'for','in','do','if','then','else','end','end'})

 

这里是一个有用的小工具,用于标识在 lua 模块 (暂时忽略那些局部声明) 中找到的所有常见全局变量:

 -- testglobal.lua

 require 'pl'

 

 local txt,err = utils.readfile(arg[1])

 if not txt then return print(err) end

 

 local globals = List()

 for t,v in lexer.lua(txt) do

     if t == 'iden' and _G[v] then

         globals:append(v)

     end

 end

 pretty.dump(seq.count_map(globals))

 

与其dump整个列表,我们把它传入seq.count_map转换为键值对,并且关联的值的表示这些值会出现在序列中的次数。典型输出如下所示:

 {

   type = 2,

   pairs = 2,

   table = 2,

   print = 3,

   tostring = 2,

   require = 1,

   ipairs = 4

 }

 

您可以进一步通过这tablex.keys以获取唯一的符号列表。当编写 '严格'的 Lua 模块时,所有全局符号都必须在文件的顶部定义为local。

lexer.scan的更多详细使用,请看示例目录中testxml.lua。

 

XML

新的 0.9.7 版本是 支持一些 XML的。这是一个大的话题,和Penlight不提供一个完整的 XML 堆栈,这是更专门库的任务。

解析和好的打印

Lua 中的半标准 XML 分析器是lua-expat。尤其是,它有lxp.lom.parse函数可以解析 XML成 Lua 对象模型 (LOM)。然而,它不提供将此数据转换回为 XML 文本的方法。如果 lua-expat可用xml.parse将使用这个函数,否则为切换回原来 Roberto Ierusalimschy 写的纯 Lua 分析器。

生成的文档对象知道如何以字符串呈现,这对于调试非常有用:

 > d = xml.parse "alice"

 > = d

 alice

 > pretty.dump (d)

 {

   {

     "alice",

     attr = {

       "id",

       id = "1"

     },

     tag = "node"

   },

   attr = {

   },

   tag = "nodes"

 }

 

数据的实际形状揭示了 LOM 的结构:

每个元素都具有其名称的tag字段

attr字段包含属性字段,并是数组。

元素的子级在元素数组里,所以d[1]d的第一个孩子。

可以认为,具有属性作为数组的attr部分不是必不可少的 (你不能依赖 XML 中的属性顺序),但这与标准一致。

lua-expatPenlight 的另一个软依赖项;一般来说,回退分析器对于简单 XML配置文件是是好足够的。doc.basic_parse不打算成为强大的符合分析器 (它只有六十行),但它可以处理简单没有的注释或 DTD 的指令的文档。它有足够的智力,忽略指令,仅此而已。

你可以得到好的打印效果,通过显式调用xml.tostring并传递给它的初始缩进和每个元素缩进:

 > = xml.tostring(d,'','  ')

 

 

   alice

 

 

第四个参数是属性缩进:

 > a = xml.parse ""

 > = xml.tostring(a,'','  ','  ')

 

 

   type='hobbit'

   name='baggins'

   age='50'

 />

分析和使用配置文件

现在用XML配置很常见。处理LOM数据和按你的想要的格式提取数据,非常简单 :

 require 'pl'

 

 local config = [[

 

     1.3

     10

     bozo

 

 ]]

 local d,err = xml.parse(config)

 

 local t = {}

 for item in d:childtags() do

     t[item.tag] = item[1]

 end

 

 pretty.dump(t)

 --->

 {

   beta = "10",

   alpha = "1.3",

   name = "bozo"

 }

 

唯一的地方是,在这里我们必须使用的Doc:childtags方法,它可以跳过任何文本元素。

本文摘录自serviceproviders.xml,它通常被发现位于Debian/Ubuntu Linux 系统/usr/share/mobile-broadband-provider-info/serviceproviders.xml

 d = xml.parse [[

 

 ...

 

     

         Cell-c

         

             

             

                 Cellcis

                 196.7.0.138

                 196.7.142.132

             

         

     

     

         MTN

         

             

             

                 196.11.240.241

                 209.212.97.1

             

         

     

     

         Vodacom

         

             

             

                 196.207.40.165

                 196.43.46.190

             

             

                 Unrestricted

                 196.207.32.69

                 196.43.45.190

             

         

     

     

         Virgin Mobile

         

             

                 196.7.0.138

                 196.7.142.132

             

         

     

 

 ....

 

 ]]

 

得到每个国家的供应商的名称非常简单:

 local t = {}

 for country in d:childtags() do

     local providers = {}

     t[country.attr.code] = providers

     for provider in country:childtags() do

         table.insert(providers,provider:child_with_name('name'):get_text())

     end

 end

 

 pretty.dump(t)

 -->

 {

   za = {

     "Cell-c",

     "MTN",

     "Vodacom",

     "Virgin Mobile"

   }

   ....

 }

 

使用'Xmlification' 生成 XML

此功能的灵感来自Oribthtmlify简化 HTML 生成,只是没有环境函数 ;tags函数返回一组给定标记名称的元素构造器。

 > nodes, node = xml.tags 'nodes, node'

 > = node 'alice'

 alice

 > = nodes { node {id='1','alice'}}

 alice

 

Lua 表的灵活性会非常有用,因此可以自然地编码的属性和元素的子级。这些标记的构造函数的参数是单个值 (如字符串) 或表,这个表的属性是命名的键和孩子们的数组值。

使用模板生成 XML 

模板是一个小的XML 文档,其中包含”$”变量。subst方法可以产生包含这些变量值的数组。请。注意指定父标记名称的方式:

 > templ = xml.parse "$name"

 > = templ:subst {tag='nodes', {id=1,name='alice'},{id=2,name='john'}}

 alicejohn

 

替代是和过滤文件相关。有关 XML 的令人讨厌的事情有,一是它是一种文档标记语言,二是它是数据语言。标准的解析器将假定你真的关心所有这些额外的文本元素。请考虑此片段,已经一个五岁孩子改变了:

 T = [[

   

     boops!

     

       

       

       whoops!

     

   

 ]]

 

标准解析器会在文本元素,虽然它使处理数据更令人恼火。

 local function parse (str)

     return xml.parse(str,false,true)

 end

 

第二个参数是指 字符串,而非文件,第三个参数表示使用 Lua 内置解析器 (而不是 LuaExpat ,如果可用),默认情况下保持字符串不感兴趣。

如何删除字符串boops!?  clone(作为一种方法调用时也称为filter) 可以复制LOM 的文档。它可以传入一个filter函数,作用到每个找到的字符串。这个函数的强大之处在于接收结构信息 — 父节点,无论是否是一个标记名称,一个文本元素或属性的名称:

 d = parse (T)

 c = d:filter(function(s,kind,parent)

     print(stringx.strip(s),kind,parent and parent.tag or '?')

     if kind == '*TEXT' and #parent > 1 then return nil end

     return s

 end)

 --->

 weather    *TAG    ?

 boops!    *TEXT    weather

 current_conditions    *TAG    weather

 condition    *TAG    current_conditions

 $condition    data    condition

 temp_c    *TAG    current_conditions

 $temp    data    temp_c

 bo    *TAG    current_conditions

 whoops!    *TEXT    bo

 

通过丢弃不是单一元素子元素的文本元素,我们可以把拉出来 'boops' 而不是 'whoops' 

使用模板提取数据

匹配在相反的方向。我们有一份文件,并想使用模式从中提取值。

这样的一个常见用途是分析 API 查询的 XML 结果。谷歌天气 API是一个很好的例子。使用pretty-print打印抓取的结果http://www.google.com/ig/api?weather=Johannesburg,ZA"如下:

 

 

mobile_row = '0' >

 

   

   

   

   

   

   

   

 

 

   

   

   

   

   

   

 

 

   

   

   

   

   

 

 ….

ml_api_reply>

 

假设上述 XML 从google被读取。这个想法写一个模板,并使用它来提取一些感兴趣的值:

 t = [[

   

     

       

       

     

   

 ]]

 

 local res, ret = google:match(t)

 pretty.dump(res)

 

的输出是:

 {

   condition = "Clear",

   temp = "24"

 }

 

match方法可以传入一个LOM文档或一些文本,可以进行文本分析。

但是如果我们需要从重复元素中提取值呢?匹配模板可能包含 '数组匹配' ,用'{{}.}' 住:

 

   {{

     

     

     

     

   }}

 

 

匹配结果是:

 {

   {

     low = "60",

     high = "89",

     day = "Sat",

     condition = "Clear",

   },

   {

     low = "53",

     high = "86",

     day = "Sun",

     condition = "Clear",

   },

   {

     low = "57",

     high = "87",

     day = "Mon",

     condition = "Clear",

   },

   {

     low = "60",

     high = "84",

     day = "Tue",

     condition = "Clear",

   }

 }

 

这一系列的表,您可以使用tablex或List重新塑造成所需的格式。和读取 Unix 密码文件与配置类似,您可以进行数组到的天气图到使用条件:

 tablex.pairmap ('|k,v| v,v.day',conditions)

 

(在这里使用替代字符串 lambda)

但是,xml 匹配可以塑造输出结构。通过替换模板的day_of_week 我们得到同样的效果 ;$是一个特殊的符号,意味着它捕获的值 (或只是捕获) 成为key。

 

请注意$NUMBER是指一个数值索引,这样, $1是生成的数组,等等的第一个元素。您可以混合使用编号和命名捕获,但它已强烈建议使编号的捕获形成适当的数组序列 (从1n包容一切)$0有特殊的含义 ;如果它是唯一的捕获 ({[0]=‘foo’}) 表可以折叠为 foo

 

   {{

     

     

     

     

   }}

 

 

现在的结果是:

 {

   Tue = {

     "60",

     "84",

     "Clear"

   },

   Sun = {

     "53",

     "86",

     "Clear"

   },

   Sat = {

     "60",

     "89",

     "Clear"

   },

   Mon = {

     "57",

     "87",

     "Clear"

   }

 }

 

将匹配应用到此配置文件会带来另一个问题,因为实际标记匹配本身有意义。

 

     1.3

     10

     bozo

 

 

标记 '通配符' 的元素名称用连字符结束。

 

     {{$value}}

 

 

你就会找到{{alpha=‘1.3’},…}。将由这返回的最方便的格式 (请注意, 的行为就像$):

 

     {{<_->$0}}

 

 

这会返回{alpha&#61;‘1.3’,beta&#61;‘10’,name&#61;‘bozo’}.

我们可以无止境地&#xff0c;玩这种游戏和编码方式的转换的捕获。但该模式足够复杂&#xff0c;不过很容易地进行转换。

 local numbers &#61; {alpha&#61;true,beta&#61;true}

 for k,v in pairs(res) do

     if numbers[v] then res[k] &#61; tonumber(v) end

 end

 

HTML 分析

HTML 是一种异常地退化形式的 XML&#xff0c;Dennis Schridde 贡献的一个功能&#xff0c;可以更轻松解析它。例如&#xff1a;

 doc &#61; xml.parsehtml [[

 

 Hello dolly

 HTML is slack

 

 ]]

 

 asserteq(xml.tostring(doc),[[

 

 Hello dolly

 HTML is slack
]])

 

也就是说&#xff0c;所有的标记都转换为小写字母&#xff0c;空的 HTML 元素如br已正确关闭 &#xff1b;不需要被引用属性。

此外&#xff0c;DOCTYPE 指令和注释被跳过。对于真正格式不好的 HTML&#xff0c;这不是你的工具 &#xff01;

 



推荐阅读
  • 本文深入探讨了 MXOTDLL.dll 在 C# 环境中的应用与优化策略。针对近期公司从某生物技术供应商采购的指纹识别设备,该设备提供的 DLL 文件是用 C 语言编写的。为了更好地集成到现有的 C# 系统中,我们对原生的 C 语言 DLL 进行了封装,并利用 C# 的互操作性功能实现了高效调用。此外,文章还详细分析了在实际应用中可能遇到的性能瓶颈,并提出了一系列优化措施,以确保系统的稳定性和高效运行。 ... [详细]
  • Android ListView 自定义 CheckBox 实现列表项多选功能详解
    本文详细介绍了在Android开发中如何在ListView的每一行添加CheckBox,以实现列表项的多选功能。用户不仅可以通过点击复选框来选择项目,还可以通过点击列表的任意一行来完成选中操作,提升了用户体验和操作便捷性。同时,文章还探讨了相关的事件处理机制和布局优化技巧,帮助开发者更好地实现这一功能。 ... [详细]
  • 在Java编程中,为了提高代码的可读性和执行效率,建议优先使用局部变量来存储方法的返回值,而不是多次调用同一个方法。这样不仅可以减少方法调用的开销,还能避免潜在的性能问题。此外,使用局部变量还可以增强代码的可维护性和调试便利性。 ... [详细]
  • 如何使用 net.sf.extjwnl.data.Word 类及其代码示例详解 ... [详细]
  • 本文介绍了Android动画的基本概念及其主要类型。Android动画主要包括三种形式:视图动画(也称为补间动画或Tween动画),主要通过改变视图的属性来实现动态效果;帧动画,通过顺序播放一系列预定义的图像来模拟动画效果;以及属性动画,通过对对象的属性进行平滑过渡来创建更加复杂的动画效果。每种类型的动画都有其独特的应用场景和实现方式,开发者可以根据具体需求选择合适的动画类型。 ... [详细]
  • Android 图像色彩处理技术详解
    本文详细探讨了 Android 平台上的图像色彩处理技术,重点介绍了如何通过模仿美图秀秀的交互方式,利用 SeekBar 实现对图片颜色的精细调整。文章展示了具体的布局设计和代码实现,帮助开发者更好地理解和应用图像处理技术。 ... [详细]
  • 在稀疏直接法视觉里程计中,通过优化特征点并采用基于光度误差最小化的灰度图像线性插值技术,提高了定位精度。该方法通过对空间点的非齐次和齐次表示进行处理,利用RGB-D传感器获取的3D坐标信息,在两帧图像之间实现精确匹配,有效减少了光度误差,提升了系统的鲁棒性和稳定性。 ... [详细]
  • 深入解析Gradle中的Project核心组件
    在Gradle构建系统中,`Project` 是一个核心组件,扮演着至关重要的角色。通过使用 `./gradlew projects` 命令,可以清晰地列出当前项目结构中包含的所有子项目,这有助于开发者更好地理解和管理复杂的多模块项目。此外,`Project` 对象还提供了丰富的配置选项和生命周期管理功能,使得构建过程更加灵活高效。 ... [详细]
  • 本文提供了 RabbitMQ 3.7 的快速上手指南,详细介绍了环境搭建、生产者和消费者的配置与使用。通过官方教程的指引,读者可以轻松完成初步测试和实践,快速掌握 RabbitMQ 的核心功能和基本操作。 ... [详细]
  • 深入解析十大经典排序算法:动画演示、原理分析与代码实现
    本文深入探讨了十种经典的排序算法,不仅通过动画直观展示了每种算法的运行过程,还详细解析了其背后的原理与机制,并提供了相应的代码实现,帮助读者全面理解和掌握这些算法的核心要点。 ... [详细]
  • Spring框架入门指南:专为新手打造的详细学习笔记
    Spring框架是Java Web开发中广泛应用的轻量级应用框架,以其卓越的功能和出色的性能赢得了广大开发者的青睐。本文为初学者提供了详尽的学习指南,涵盖基础概念、核心组件及实际应用案例,帮助新手快速掌握Spring框架的核心技术与实践技巧。 ... [详细]
  • 本文详细探讨了C语言中`extern`关键字的简易编译方法,并深入解析了预编译、`static`和`extern`的综合应用。通过具体的代码示例,介绍了如何在不同的文件之间共享变量和函数声明,以及这些关键字在编译过程中的作用和影响。文章还讨论了预编译过程中宏定义的使用,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • 本文详细解析了 MySQL 5.7.20 版本中二进制日志(binlog)崩溃恢复机制的工作流程。假设使用 InnoDB 存储引擎,并且启用了 `sync_binlog=1` 配置,文章深入探讨了在系统崩溃后如何通过 binlog 进行数据恢复,确保数据的一致性和完整性。 ... [详细]
  • 本文介绍了一种简化版的在线购物车系统,重点探讨了用户登录和购物流程的设计与实现。该系统通过优化界面交互和后端逻辑,提升了用户体验和操作便捷性。具体实现了用户注册、登录验证、商品浏览、加入购物车以及订单提交等功能,旨在为用户提供高效、流畅的购物体验。 ... [详细]
  • 深入解析 iOS Objective-C 中的对象内存对齐规则及其优化策略
    深入解析 iOS Objective-C 中的对象内存对齐规则及其优化策略 ... [详细]
author-avatar
书友57087250
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有