• lua工具库penlight--08额外的库(一)


    额外的库

    在这一节中的不再被认为是Penlight核心部分,但在需要时仍提供专门的功能。

     

     

    简单的输入的模式

    Lua 的字符串模式匹配是非常强大,通常您将不需要传统的正则表达式库。即便如此,有时 Lua 代码结束看上去像 Perl,因为字符串模式不容易阅读,尤其是对普通读者而言这段代码需要了解三种不同的日期格式:

     -- parsing dates using Lua string patterns

     months={Jan=1,Feb=2,Mar=3,Apr=4,May=5,Jun=6,

     Jul=7,Aug=8,Sep=9,Oct=10,Nov=11,Dec=12}

     

     function check_and_process(d,m,y)

         d = tonumber(d)

         m = tonumber(m)

         y = tonumber(y)

         ....

     end

     

     for line in f:lines() do

         -- ordinary (English) date format

         local d,m,y = line:match('(%d+)/(%d+)/(%d+)')

         if d then

             check_and_process(d,m,y)

         else -- ISO date??

             y,m,d = line:match('(%d+)%-(%d+)%-(%d+)')

             if y then

                 check_and_process(d,m,y)

             else -- <day> <month-name> <year>?

                 d,mm,y = line:match('%(d+)%s+(%a+)%s+(%d+)')

                 m = months[mm]

                 check_and_process(d,m,y)

             end

         end

     end

     

    这些不是特别困难的模式,但典型问题已经出现,例如,不得不转义 ' — '。此外, string.match返回其捕获,这样,我们被迫使用略显尴尬的嵌套的 if 语句。

    验证码检验问题使用正则表达式的人试图强制约束 (如一年不能超过四位数) 。我们应该享受匹配,而不是拿着锤子砸自己。

    pl.sip提供了简单、 直观的方式来检测字符串中的模式和提取的相关部分。

     > sip = require 'pl.sip'

     > dump = require('pl.pretty').dump

     > res = {}

     > c = sip.compile 'ref=$S{file}:$d{line}'

     > = c('ref=hello.c:10',res)

     true

     > dump(res)

     {

       line = 10,

       file = "hello.c"

     }

     > = c('ref=long name, no line',res)

     false

     

    sip.compile可以从给定字符串和表创建一个模式匹配器函数。如果匹配字符串,则返回true ,根据模式中命名字段填充该表。

    这里是另一个版本的日期分析器:

     -- using SIP patterns

     function check(t)

         check_and_process(t.day,t.month,t.year)

     end

     

     shortdate = sip.compile('$d{day}/$d{month}/$d{year}')

     longdate = sip.compile('$d{day} $v{mon} $d{year}')

     isodate = sip.compile('$d{year}-$d{month}-$d{day}')

     

     for line in f:lines() do

         local res = {}

         if shortdate(str,res) then

             check(res)

         elseif isodate(str,res) then

             check(res)

         elseif longdate(str,res) then

             res.month = months[res.mon]

             check(res)

         end

     end

     

    SIP 模式'$'开始 ,之后跟着单字母类型,后面大括号中的是可选变量。

     Type    Meaning

     v         variable, or identifier.

     i          possibly signed integer

     f          floating-point number

     r          'rest of line'

     q         quoted string (either ' or ")

     p         a path name

     (         anything inside (...)

     [         anything inside [...]

     {         anything inside {...}

     <         anything inside <...>

     [---------------------------------]

     S         non-space

     d         digits

     ...

     

    如果类型不是 v、 i、 f、 或 之一,它被假定为标准 Lua 字符。你在模式中的任何空格将匹配任意数目的空格。'神奇字符串的任何字符均被转义。

    SIP 捕获 (像$v{mon}) 不需要进行命名。您可以使用只是$v,但你必须保持一致 ;如果一种模式包含未命名的捕获,然后所有捕获必须都是未命名。在这种情况下,结果表是一个简单的值列表。

    sip.match是有用的快捷方式,如果你喜欢你 '。(它将缓存结果,所以它显式sip.compile快些.)

     > sip.match('($q{first},$q{second})','("john","smith")',res)

     true

     > res

     {second='smith',first='john'}

     > res = {}

     > sip.match('($q,$q)','("jan","smit")',res)  -- unnamed captures

     true

     > res

     {'jan','smit'}

     > sip.match('($q,$q)','("jan", "smit")',res)

     false   ---> oops! Can't handle extra space!

     > sip.match('( $q , $q )','("jan", "smit")',res)

     true

     

    作为一般规则,允许您模式中的空白。

    最后,放在模式的结尾的 '$' 意味着 '捕获的在第一个非空格开头的行。

     > sip.match('( $q , $q ) $','("jan", "smit") and a string',res)

     true

     > res

     {'jan','smit','and a string'}

     > res = {}

     > sip.match('( $q{first} , $q{last} ) $','("jan", "smit") and a string',res)

     true

     > res

     {first='jan',rest='and a string',last='smit'}

     

     

     

    命令行程序与 Lapp

    pl.lapp小而专注的Lua 模块,它的目的是要使标准命令行解析更方便和直观。它实现了 GNU 风格,即以短横线'-'或长横线--'开始的字母。一般带参数的选项期望找到下一个输入作为它的参数 (例如 ' gcc test.c -o test'),单个短选项可以忽略空格 (例如 'head  -n4  test.c' gcc   -I/usr/include/lua/5.1 …)

     

    Lapp 可能将参数转换为等效的 Lua 类型,即转换数字文件名转换为文件对象。如果任何转换失败,或缺少所需的参数,则将发出错误消息、 用文本出。所以有两个必要的任务,提供的标志和选项的名字,并将它们和类型关联。

     

    对于任何非平凡的脚本,或仅为了个人消遣,有必要提供使用说明Lapp 的新颖性是定义松散格式字符串用法而且可以指定参数的名称和类型。

    示例:

     -- scale.lua

       lapp = require 'pl.lapp'

       local args = lapp [[

       Does some calculations

         -o,--offset (default 0.0)  Offset to add to scaled number

         -s,--scale  (number)  Scaling factor

          <number> (number )  Number to be scaled

       ]]

     

       print(args.offset + args.scale * args.number)

     

    这里是命令行的会话使用此脚本:

     $ lua scale.lua

     scale.lua:missing required parameter: scale

     

     Does some calculations

      -o,--offset (default 0.0)  Offset to add to scaled number

      -s,--scale  (number)  Scaling factor

       <number> (number )  Number to be scaled

     

     $ lua scale.lua -s 2.2 10

     22

     

     $ lua scale.lua -s 2.2 x10

     scale.lua:unable to convert to number: x10

     

     ....(usage as before)

     

    有两种类型的 Lapp 用法让字符串意义。短选项,可以选择相应的长选项。可遵循括号中的类型说明符。同样, '<'  PARMETER ' >' 开头的参数行,后面跟着的是类型说明符。类型说明符是任一形式'(默认 'VALUE')' 或 '(' TYPE')' ;默认的说明符意味着选项或参数有默认值,并不是必需的。类型是一个 '字符串'、 ''、 '文件输入或 '文件VALUE是一个数字,('stdin'、 'stdout'、 'stderr') 之一或者是标记。这行的其余不会被分析,可以用作注释

     

    此脚本在输出表中显示的字段与指定的参数名称之间的关系。

     -- simple.lua

     local args = require ('pl.lapp') [[

     Various flags and option types

       -p          A simple optional flag, defaults to false

       -q,--quiet  A simple flag with long name

       -o  (string)  A required option with argument

       <input> (default stdin)  Optional input file parameter

     ]]

     

     for k,v in pairs(args) do

         print(k,v)

     end

     

    上面显示了args表的所有参数 ;请注意,args.quiet 已经成为为 true,因为它被指定 ;args.p 默认为 false。如果有一个长命名选项,选项中用作局部名称因为默认的类型是布尔类型,对于简单的标志,它的类型或默认值不是必须的

     $ simple -o test -q simple.lua

     p       false

     input   file (781C1BD8)

     quiet   true

     o       test

     input_name      simple.lua

     D:devlualapp>simple -o test simple.lua one two three

     1       one

     2       two

     3       three

     p       false

     quiet   false

     input   file (781C1BD8)

     o       test

     input_name      simple.lua

     

    参数输入已设置为打开只读文件对象 — — 我们知道它必须是一个只读的文件,因为它是默认值的类型。input_name字段会自动生成 ,因为它经常用来访问原始文件名。

    请注意,提供的任意额外参数会放到整数索引表里,即 args [i] i表示到 #args 之间的值

    对有良好定义明确任务的短脚本文件真的不必显式关闭因为垃圾收集文件对象的结果就是关闭它们。

     

  • 相关阅读:
    Python shutil模块
    configparser模块来生成和修改配置文件
    用random模块实现验证码
    python 正则re模块
    python 装饰器
    python迭代器和生成器
    python替换一个文件里面的特定内容
    广告资源收集
    Java 语言中 Enum 类型的使用介绍
    FreeMarker + xml 导出word
  • 原文地址:https://www.cnblogs.com/xdao/p/lua_penlight08_1.html
Copyright © 2020-2023  润新知