额外的库

在这一节中的库不再被认为是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、 r 或 q 之一,它被假定为标准 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:\dev\lua\lapp>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表示1 到 #args 之间的值。

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

最新文章

  1. 了解Package Configurations
  2. Shou.TV 招聘【北京】— — 生效中
  3. 2016 Web开发资源工具大搜罗
  4. CSS Shake – 摇摆摇摆!动感的 CSS 抖动效果
  5. [Java]double初始化问题
  6. windows 10启动盘制作工具
  7. 在AX4.0中使用C#脚本的实现
  8. Quartus II 11.0 开始使用
  9. oracle定时备份与删除N天前备份文件
  10. 解决win10 iot VS编程出现的无法引用错误
  11. IDEA导入maven项目的步骤
  12. 51nod_1100:斜率最大
  13. Struts2多文件上传原理和示例
  14. html+css常用小笔记(持续更新)
  15. python 全栈开发,Day72(昨日作业讲解,昨日内容回顾,Django多表创建)
  16. css拾遗(一)(inline-block,absolute)
  17. [&quot;1&quot;, &quot;2&quot;, &quot;3&quot;].map(parseInt) 为何返回[1,NaN,NaN]
  18. spring mongo data api learn
  19. Java并发编程(九)线程间协作(下)
  20. Whoops, looks like something went wrong

热门文章

  1. iFrame的妙用
  2. win8自带输入法如何切换全角、半角操作流程
  3. Sqlite数据库字符串处理函数replace
  4. FrameWork数据权限浅析4之基于多维度配置表实现行级数据安全
  5. Android DataBinding库(MVVM设计模式)
  6. TypeScript 面向对象基础知识
  7. spring Log4j关于No appenders could be found for logger的警告
  8. ORC 资料Mark
  9. Js/jQuery实时监听输入框值变化
  10. shell监控脚本实例—监控mysql主从复制