- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个 Flexlm/Flexnet 许可服务,我想解析这个服务的输出。所有输出都是多行的结构化 block 。我的第一步是解析 lmutil lmstat -c <port@server> -a
的输出使用许可证和增量。
我尝试使用 Ruby 和 Parslet。所有行都被单独解析。我有一个规则来解析特定类型行的重复,但我无法解析结构化的行 block 。
我正在寻找定义在多行结构化 block 中放置“换行”语句的位置的法则(在此上下文中最好的词是“规则”)。
我使用 Debian Jessie(稳定/x86_64)和 Ruby 2.1.5p273 以及 Parslet 1.6.1-1。
我已经联系了作者,他很抱歉,但他没有足够的时间来帮助我。看到的网页是:
我花了很多时间试图理解如何构建多行结构化 block 的规则。下面是我的源代码,其中包含所有测试字符串和输出。
我的方法是构建:
我不确定第 3 点,我完全迷失了“4”和“5”。
在此先感谢您的帮助。 [ 2017 年 7 月 14 日:部分代码已删除]
#!/usr/bin/env ruby
# This code try to parse the output of 'lmutil lmstat -c <port@server> -a'.
require 'parslet'
require 'parslet/convenience'
require 'pp'
### Begin of the class Lmstat
class Lmstat < Parslet::Parser
###
# Small parts to parse
rule(:digit) { match(/\d/).repeat(1) }
rule(:space) { str(' ').repeat }
rule(:eof) { any.absent? }
rule(:blank_line) { space.maybe >> newline >> space.maybe }
rule(:newline) { str("\r").maybe >> str("\n") }
rule(:txt) { match(/[\w\d\s,_.'",-:]/).repeat }
def parenthese( atom, qte='()' )
if (qte == '()' )
str('(') >> atom >> str(')')
else
str(qte) >> atom >> str(qte)
end
end
###
###
# The header is not parsed for the moment, while I can't
rule (:header) do
# Not define until the other parts are OK.
end
rule(:feature_line) do
feature_usage.as(:feature_line) >> # newline >>
feature_line_id.as(:feature_line_id).repeat.as(:f_line)
end
rule(:feature_line_id) do
feature_version >> newline >> feature_type >> newline >>
feature_user_group >> newline
end
rule(:feature_line_id_group) do
(newline >> feature_line_id).repeat(1).as(:f_line_group) >> newline
end
rule(:feature_usage) do
str("Users of ") >> feature.as(:feature_usage) >> str(':') >> space >>
parenthese( feature_used ) >> space.maybe
end
rule(:feature) { match(/[\w_-]/).repeat }
# Total of 1 license issued; Total of 0 licenses in use
rule(:feature_used) do
feature_token.as(:feature_token_issued) >>
feature_token.as(:feature_token_used) >> space.maybe >> newline.maybe
end
# (Total of 1 license issued; Total of 0 licenses in use)
rule(:feature_token) do
space.maybe >> str('Total of ') >> digit.repeat.as(:feature_token_value) >>
space >> license >> issued_used >>
str(';').maybe >> space.maybe
end
rule(:license) { str('license') >> str('s').maybe >> space }
rule(:issued_used) do
str('issued') | str('in use')
end
# v2015.1231
rule(:version) { match(/[\w\d.-]/).repeat }
# "incr-1"
rule(:vendor) { match(/[\w-]/).repeat }
# "incr-1" v2015.1231, vendor: ansoftd
rule(:feature_version) do
# newline >>
space.maybe >> parenthese( feature.as(:feature), '"' ) >>
space >> version.as(:version) >> str(', vendor: ') >>
vendor.as(:vendor) >> space.maybe >>
str(', expiry: ').maybe >> match(/[\w\d-]/).repeat.as(:expiration).maybe
end
# floating license
# nodelocked license, locked to "ID=12345"
rule(:feature_type) do
space.maybe >>
( (space.maybe >> str("floating license").as(:floating) >> space.maybe) |
(space.maybe >> str('nodelocked license, locked to "ID=') >>
digit.as(:license_id) >> str('"') >> space.maybe)).as(:feature_type) >>
space.maybe
end
# \t 28 RESERVATIONs for GROUP Better_Group (server/27000)
rule(:reserve) do
space.maybe >> str("\t").maybe >> digit.as(:reserve_value) >>
str(" RESERVATION") >> str("s").maybe >> str(" for ") >>
word.as(:reserve_type) >> space >> word.as(:reserve_who) >>
space >>
parenthese( host.as(:server) >> str("/") >> digit.as(:port) )
end
rule(:reserve_group) do
(newline >> reserve).repeat(1).as(:reservation)
end
rule(:feature_user) do
space.maybe >>
word.as(:login) >> space >> host.as(:host_user) >> space >> host.as(:id) >>
space >> parenthese( version.as(:version) ) >> space >> port >> date_queue
end
rule(:feature_user_group) do
(newline >> feature_user).repeat(1).as(:feature_user_group)
end
# queued for 1 license
rule(:queue) do
str('queued for ') >> digit.as(:queued) >> str(' license') >> str('s').maybe
end
rule(:date_queue) do
( ( str(',') >> space >> date >> cmt.as(:comment)) | (space >> queue) )
end
rule(:cmt) do
space.maybe >> match(/[^\r\n]/).repeat#.as(:cmt)
end
rule(:word) { match(/[\w\d-]/).repeat }
rule(:host) { match(/[\w\d_.-]/).repeat }
rule(:port) do
parenthese( host.as(:server) >> str('/') >> digit.as(:server_port) >>
space >> digit.as(:vendor_port) )
end
rule(:date) do
str('start ') >> word.as(:date_dayname) >> space >>
digit.as(:date_month) >> str('/') >> digit.as(:date_day) >> space >>
digit.as(:date_hour) >> str(':') >> digit.as(:date_minute)
end
end
### End of the class Lmstat
###
# Some multiline tests case.
t_feature_line_id = %q{ "incr-2" v9999.9999, vendor: vendor-daemon
floating license
henry abc057 abc057 (v2015.0623) (shoe/28512 3886) queued for 1 license
simon abc057 abc057 (v2014.1110) (shoe/28512 4166), start Fri 11/20 15:37, 10 licenses
simon abc057 abc057 (v2014.1110) (shoe/28512 4166), start Fri 11/20 15:37 queued for 1 license
}
t_feature_line_id_group = %q{ "incr-2" v9999.9999, vendor: vendor-daemon
floating license
henry abc057 abc057 (v2015.0623) (shoe/28512 3886) queued for 1 license
jason abc057 abc057 (v2015.0623) (shoe/28512 3886), start Fri 11/20 14:41
simon abc057 abc057 (v2014.1110) (shoe/28512 4166), start Fri 11/20 15:37, 10 licenses
simon abc057 abc057 (v2014.1110) (shoe/28512 4166), start Fri 11/20 15:37 queued for 1 license
"inc2" v9999.9999, vendor: inc2vendor
floating license
simon abc057 abc057 (v2014.1110) (shoe/28512 4166), start Fri 11/20 15:37, 10 licenses
simon abc057 abc057 (v2014.1110) (shoe/28512 4166), start Fri 11/20 15:37 queued for 1 license }
t_feature_line = %q{Users of ansys: (Total of 9 licenses issued; Total of 6 licenses in use)
"incr-2" v9999.9999, vendor: vendor-daemon
floating license
jason abc057 abc057 (v2015.0623) (shoe/28512 3886), start Fri 11/20 14:41
simon abc057 abc057 (v2014.1110) (shoe/28512 4166), start Fri 11/20 15:37, 10 licenses
simon abc057 abc057 (v2014.1110) (shoe/28512 4166), start Fri 11/20 15:3}
t_feature_line_group = %q{
"incr-2" v9999.9999, vendor: vendor-daemon
floating license
jason abc057 abc057 (v2015.0623) (shoe/28512 3886), start Fri 11/20 14:41
simon abc057 abc057 (v2014.1110) (shoe/28512 4166), start Fri 11/20 15:37, 10 licenses
simon abc057 abc057 (v2014.1110) (shoe/28512 4166), start Fri 11/20 15:37 queued for 1 license
"incr-2" v9999.9999, vendor: vendor-daemon
floating license
jason abc057 abc057 (v2015.0623) (shoe/28512 3886), start Fri 11/20 14:41
simon abc057 abc057 (v2014.1110) (shoe/28512 4166), start Fri 11/20 15:37, 10 licenses
simon abc057 abc057 (v2014.1110) (shoe/28512 4166), start Fri 11/20 15:37}
t_feature_user= %q{jason abc057 abc057 (v2015.0623) (shoe/28512 3886), start Fri 11/20 14:41}
t_feature_group = %q{ "incr-2" v9999.9999, vendor: vendor-daemon
floating license
jason abc057 abc057 (v2015.0623) (shoe/28512 3886), start Fri 11/20 14:41
simon abc057 abc057 (v2014.1110) (shoe/28512 4166), start Fri 11/20 15:37, 10 licenses
jessica abc057 abc057 (v2014.1110) (shoe/28512 4166), start Fri 11/20 15:37
"MATLAB" v35, vendor: MLM, expiry: 01-jan-0000
nodelocked license, locked to "ID=12345"
albert node7563 node7563 (v34) (shoe/27000 201), start Mon 5/23 6:16 (linger: 1235700)
victoria abc087 /dev/pts/1 (v29) (shoe/27000 3401), start Mon 5/23 6:30}
###
###
# Method to test the parsing.
def parse_method(method,str)
lmstat = Lmstat.new
unless lmstat.respond_to?(method)
raise ArgumentError,
"\n\n\t***** ERROR: Unknown method -> '#{method}' ******\n\n",
caller[1..-1]
end
begin
m = "lmstat.#{method}.parse('"+ str + '\')'
puts "=> Test of #{m}"
eval (m)
rescue Parslet::ParseFailed => failure
puts failure.cause.ascii_tree
end
end
###
###
# Not called if 'irb' is used to load the program.
if __FILE__ == $PROGRAM_NAME
puts "\n ###### Multilines #####"
parse_method('feature_user_group',t_feature_user_group)
parse_method("feature_line_id",t_feature_line_id)
pp parse_method("feature_line_id_group",t_feature_line_id_group)
end
输出 [ 07/13/2017 : 删除以放置功能版本 ]
[更新 - 2017 年 4 月 29 日 - 问题已解决]感谢 Nigel Thorne 的回答,它解决了我的问题。我已按照您的建议更正了“空格”的规则。
[ 2014 年 7 月 13 日:删除一些文本以放置功能齐全的版本。 ]
[更新 - 07/13/2017 - 测试解析的应用程序]
我已经完成了一个应用程序,用于测试使用 Ruby 和 Parslet 解析 lmstat 的输出。由于解析依赖于每个编辑器,有些情况可能无法涵盖,但使用了 30 多个许可服务来验证解析。
我可以给 3 个文件:
irb
更好。 session 。它使用 YAML 格式从 STDIN 读取经过解析的 lmstat 输出。一个例子:
~/bin/lmutil lmstat -a -c 1234@licserver | ./parse_lmstat.rb --screen | ./display_lmstat.rb
一个已知错误:当 [CTRL-C] 完成时,信号似乎没有被很好地捕获,Ruby 在某些情况下会发送一些错误消息。
现在,我梦想有一个小型 WEB 应用程序(SINATRA?)来选择许可服务器并显示数据,但我不会说 HTML 或 CSS ...任何帮助将不胜感激;-)
由于 30000 个字符的限制,您将在下面仅找到用于解析和转换 lmstat 输出的类。
#!/usr/bin/env ruby
#
# class_lmstat.rb
#
# This code try to parse the output of 'lmutil lmstat -c <port@server> -a'.
#
# Scapin - 11/07/2017
#
# For the Stackoverflow forums
#
require 'parslet'
require 'parslet/convenience'
require 'open3'
### Begin of the class Lmstat
class Lmstat < Parslet::Parser
###
# Small parts to parse
rule(:digit) { match(/\d/).repeat(1) }
rule(:space) { str(' ').repeat(1) }
rule(:eof) { any.absent? }
rule(:blank_line) { space.maybe >> newline >> space.maybe }
rule(:newline) { str("\r").maybe >> str("\n") }
rule(:txt) { match(/[\w_.\)\('\t ",-:\\]/).repeat }
rule(:word) { match(/[\w-]/).repeat }
rule(:host) { match(/[\w_\.-]/).repeat }
rule(:cnx_id) { match(/[\/\w_.:]/).repeat }
rule(:cmt) { space.maybe >> match(/[^\r\n]/).repeat }
rule(:error_code) { match(/[,\d-]/).repeat }
def parenthese( atom, qte='()' )
if (qte == '()' )
str('(') >> atom >> str(')')
else
str(qte) >> atom >> str(qte)
end
end
###
root(:lmstat)
rule(:lmstat) do
(header.as(:header) >> body.repeat.as(:service) >> newline).as(:lmstat)
end
###
# The header is not parsed for the moment, while I can't
# handle the multiline block correctly.
#
# lmutil - Copyright (c) 1989-2013 Flexera Software LLC. All Rights Reserved.
# Flexible License Manager status on Fri 11/20/2015 16:39
#
# License server status: 1141@lic-server
# License file(s) on lic-server: /opt/license/soft/vendor1.lic:/opt/license/soft/vendor2.lic:
#
# lic-server: license server UP (MASTER) v11.13
#
# Vendor daemon status (on lic-server):
#
# vendor-daemon: UP v11.13
# Feature usage info:
#
###
rule (:header) do
copyright >> status_date >> newline >>
server >> license_file >> newline >>
server_status >> newline >>
vendor_daemon_status >> newline
end
rule (:body) do
(vendor_daemon.as(:vendor_daemon) >> feature_info.maybe >> newline >>
feature_line.repeat.maybe.as(:features))
end
# lmutil - Copyright (c) 1989-2013 Flexera Software LLC. All Rights Reserved.
rule (:copyright) do
space.maybe >> (str("lmutil - Copyright ") >> match(/./).repeat).as(:copyright) >> newline
end
# Flexible License Manager status on Fri 11/20/2015 16:39
rule(:status_date) do
space.maybe >> str("Flexible License Manager status on ") >>
word.as(:status_dayname) >> space >>
digit.as(:status_month) >> str("/") >> digit.as(:status_day) >>
str("/") >> digit.as(:status_year) >>
str(" ") >> digit.as(:status_hour) >>
str(":") >> digit.as(:status_min) >> newline
end
rule(:server) do
str("License server status: ") >>
digit.as(:server_port1) >> str("@") >> host.as(:server1) >>
( str(",") >> digit.as(:server_port2) >> str("@") >> host.as(:server2) >>
str(",") >> digit.as(:server_port3) >> str("@") >> host.as(:server3) ).maybe >>
newline
end
# License file(s) on lic-server: /opt/license/soft/licfile-1.lic:/opt/soft/licfile-2.lic:
rule(:license_file) do
space.maybe >> str("License file(s) on ") >>
match(/[\w\d._-]/).repeat.as(:license_files_server) >>
str(": ") >> txt.as(:license_files_names) >> newline
end
rule(:server_status) do
(space.maybe >> host.as(:server_host) >> str(": ") >>
( server_up | server_down) >> newline).repeat(0).as(:server_list)
end
rule(:server_up) do
str("license server ")>>str("UP").as(:server_up)>>
server_pos.maybe >> str(" ") >> cmt.as(:server_version)
end
rule(:server_pos) do
space >> parenthese( match(/[A-Za-z]/).repeat.as(:server_role))
end
# licserver: Cannot connect to license server system. (-15,570:115 "Operation now in progress")
rule(:server_down) do
space.maybe >> str("Cannot connect to license server system").as(:server_down) >>
str(". ") >> cmt.as(:server_error)
end
rule(:vendor_daemon_status) do
str("Vendor daemon status (on ") >> host.as(:server_daemon) >>
str("):") >> space.maybe >> newline
end
rule(:vendor_daemon) do
( vendor_daemon_up | vendor_daemon_down )
end
rule(:vendor_daemon_up) do
space.maybe >> word.as(:daemon) >> str(": ") >> word.as(:daemon_status) >>
space >> host.as(:daemon_version) >> newline
end
rule(:vendor_daemon_down_ini) do
space.maybe >> word.as(:daemon) >> str(": The desired vendor daemon is down. ") >>
parenthese( error_code.as(:daemon_status) ) >> space.maybe >> newline
end
# \n\n dconcept: No socket connection to license server manager. (-7,96)
rule(:vendor_daemon_down) do
space.maybe >> word.as(:daemon) >> str(": The desired vendor daemon is down. ") >>
parenthese( error_code.as(:daemon_status) ) >> space.maybe >> newline
space.maybe >> word.as(:vendor_daemon_down_msg_feature).maybe >>
str(': No socket connection to license server manager.').maybe >> space.maybe >>
cmt.as(:vendor_daemon_down_msg).maybe >> newline.maybe
end
rule(:feature_info) do
space.maybe >> str("Feature usage info:") >> space.maybe >> newline
end
###
# Users of soft_a: (Total of 1 license issued; Total of 0 licenses in use)
#
# "incr-1" v2015.1231, vendor: soft_ad
# floating license
#
# 28 RESERVATIONs for GROUP Better_Group (server/27000)
# 1 RESERVATION for USER toni (server/27000)
# scott abc056 abc056 (v2015.0623) (shoe/28512 3644), start Fri 11/20 15:45, 2 licenses
# scott abc056 abc056 (v2015.0623) (shoe/28512 4669), start Fri 11/20 15:45, 10 licenses
rule(:feature_line) do
feature_usage.as(:feature_line) >> newline >>
feature_line_id.repeat(0).as(:feature_line_id)
end
# "incr-1" v2015.1231, vendor: soft_ad
# floating license
#
# scott abc056 abc056 (v2015.0623) (shoe/28512 3644), start Fri 11/20 15:45, 2 licenses
# scott abc056 abc056 (v2015.0623) (shoe/28512 4669), start Fri 11/20 15:45, 10 licenses
rule(:feature_line_id) do
feature_version >> newline >> feature_type >> newline >>
# ( reserve.as(:reservation) | feature_user.as(:user)).repeat(1).as(:users) >> newline
( reserve.as(:reservation) | feature_user.as(:user)).repeat(1).as(:who) >> newline
end
# Users of soft_a: (Total of 1 license issued; Total of 0 licenses in use)
# Users of SOFT_B: (Uncounted, node-locked)
# Users of soft_c: (Error: 6 licenses, unsupported by licensed server)
rule(:feature_usage) do
str("Users of ") >> feature.as(:feature_name) >> str(':') >> space >>
parenthese( feature_used ) >> space.maybe >> newline
end
# Total of 1 license issued; Total of 0 licenses in use
# Uncounted, node-locked
rule(:feature_used) do
( ( feature_token.as(:feature_token_issued) >> feature_token.as(:feature_token_used)) |
( word.as(:feature_token_issued) >> str(', ') >> word.as(:feature_token_used) ) |
( str('Error: ') >> digit.repeat.as(:feature_token_error) >> space >> str( 'license') >>
str('s').maybe >> str(', ') >>
match(/[\w_', :-]/).repeat.as(:feature_token_error_cause) ) ) >>
space.maybe >> newline.maybe
end
# (Total of 1 license issued; Total of 0 licenses in use)
rule(:feature_token) do
space.maybe >> str('Total of ') >> digit.repeat.as(:feature_token_value) >>
space >> license >> issued_used >>
str(';').maybe >> space.maybe
end
rule(:license) { str('license') >> str('s').maybe >> space }
rule(:issued_used) do
str('issued') | str('in use')
end
# v2015.1231
rule(:version) { match(/[\w\d.-]/).repeat }
# "incr-1"
rule(:vendor) { match(/[\w-]/).repeat }
rule(:feature) { match(/[\w\d\/_+-]/).repeat }
# "incr-1" v2015.1231, vendor: soft_ad
rule(:feature_version) do
# newline >>
space >> parenthese( feature.as(:feature), '"' ) >>
space >> version.as(:version) >> str(', vendor: ') >>
vendor.as(:vendor) >> space.maybe >>
str(', expiry: ').maybe >> match(/[\w\d-]/).repeat.as(:expiration).maybe
end
rule(:feature_type) do
space >> ( float_type | node_type ).as(:feature_type)
end
# floating license
rule(:float_type) do
str("floating license").as(:floating) >> cmt.maybe >> newline
end
# nodelocked license, locked to "ID=654321"
# nodelocked license locked to NOTHING (hostid=ANY)
# uncounted nodelocked license locked to NOTHING (hostid=ANY)
# uncounted nodelocked license, locked to Vendor-defined "PTC_HOSTID=01-0A-01-0A-01"
rule(:node_type) do
str('uncounted ').maybe >> str("nodelocked license") >> str(',').maybe >> str(' locked to ').maybe >>
( ( str('"ID=') >> digit.as(:nodelocked_id) >> str('"') ) |
( host.as(:nodelocked_to) >> space >> parenthese(str('hostid=') >> host.as(:nodelocked_hostid)) ) |
( host.as(:nodelocked_to) >> space >>
parenthese(match(/[\w:_=' -]/).repeat.as(:nodelocked_hostid), '"') ) ) >>
space.maybe >> newline
end
# \t 28 RESERVATIONs for GROUP Better_Group (server/27000)
rule(:reserve) do
space.maybe >> str("\t").maybe >> digit.as(:reserve_value) >>
str(" RESERVATION") >> str("s").maybe >> str(" for ") >>
word.as(:reserve_type) >> space >> word.as(:reserve_who) >>
space >>
parenthese( host.as(:server) >> str("/") >> digit.as(:port) ) >>
newline
end
rule(:feature_user) do
(u_std | u_aselta | u_ans | u_c1 | u_c2 )
end
# scott abc056 abc056 (v2015.0623) (shoe/28512 3644), start Fri 11/20 15:45, 2 licenses
# albert node7563 node7563 (v34) (shoe/27000 201), start Mon 5/23 6:16 (linger: 1235700)
# hector node088 dev/tty (v2015.0312) (licserver/1446 3730), start Thu 11/19 9:08
# will pim.my.domain.org pim.my.domain.org 6656 (v2016.1129) (licserver/1446 2216), start Fri 5/12 14:51
rule(:u_std) do
space >> word.as(:login) >> space >> host.as(:host_user) >> space >>
cnx_id.as(:host_id) >>
space >> parenthese( version.as(:version) ) >> space >> port >> date_queue >>
newline
end
# scott cat :0 Token Lic (v7.000) (shoe/5300 15434), start Thu 7/6 17:07
rule(:u_c1) do
space >> word.as(:login) >> space >> host.as(:host_user) >> space >>
cnx_id.as(:host_id) >> space >> match(/[^(]/).repeat.as(:common_name) >>
parenthese( version.as(:version) ) >> space >> port >> date_queue >>
newline
end
# jessie cat bird:1144.0 APS Multi-core (Max. 16 cores) (v11.100) (licserver/5303 13188), start Thu 7/6 15:22, 4 licenses
rule(:u_c2) do
space >> word.as(:login) >> space >> host.as(:host_user) >> space >>
cnx_id.as(:host_id) >> space >> match(/[^(]/).repeat.as(:common_name) >>
str('(') >> match(/[^)]/).repeat.as(:common_info) >> str(')') >> space >>
parenthese( version.as(:version) ) >> space >> port >> date_queue >>
newline
end
# tiger pam.my.domain.org pam.my.domain.org 6656 (v2016.1129) (licserver/1446 2216), start Fri 5/12 14:51
rule(:u_ans) do
space >> word.as(:login) >> space >> host.as(:host_user) >> space >>
cnx_id.as(:host_id) >> ( space >> host.as(:further) ).maybe >>
space >> parenthese( version.as(:version) ) >> space >> port >> date_queue >>
newline
end
# clark node07 SOMETHING Inscale / grid (worker) (v1.0) (licserv01/27016 5506), start Fri 4/28 13:42, 4 licenses
# bunny orca SOMETHING Inscale / graphical (v1.0) (licserv01/27016 650), start Thu 4/13 10:27
rule(:u_aselta) do
space >> word.as(:login) >> space >> host.as(:host_user) >> space >>
word.as(:daemon) >> space >> word.as(:soft) >> str(" / ") >>
word.as(:function) >> (space >> parenthese( word.as(:tools) )).maybe >>
space >> parenthese( version.as(:version) ) >> space >> port >> date_queue >>
newline
end
# queued for 1 license
rule(:queue) do
str('queued for ') >> digit.as(:queued) >> str(' license') >> str('s').maybe
end
rule(:lic) do
str(',') >> space >> digit.as(:licenses) >> str(' license') >> str('s').maybe
end
rule(:date_queue) do
( ( str(',') >> space >> date >> ( lic | cmt.as(:comment))) | (space >> queue) )
end
rule(:port) do
parenthese( host.as(:server) >> str('/') >> digit.as(:server_port) >>
space >> digit.as(:vendor_port) )
end
rule(:date) do
str('start ') >> word.as(:date_dayname) >> space >>
digit.as(:date_month) >> str('/') >> digit.as(:date_day) >> space >>
digit.as(:date_hour) >> str(':') >> digit.as(:date_minute)
end
end
### End of the class Lmstat
### Begin of the class Trans
class Trans < Parslet::Transform
rule(:feature_token_value => simple(:v)) { Integer(v) }
rule(:user => subtree(:t)) do
if ( t.has_key?(:date_month) )
cal = { "Sun"=>"Dimanche", "Mon"=>"Lundi", "Tue"=>"Mardi",
"Wed"=>"Mercredi", "Thu"=>"Jeudi", "Fri"=>"Vendredi"}
clock = Time.now
# Addition of keys
t.merge!( { :date_year => 0, :since => "", :delay_min => 0, :delay_string => ""})
# Convert to integer
t[:date_minute] = t[:date_minute].to_s.sub(/^0/,"") if (t.has_key?(:date_minute))
t.each do |k,v|
[ :server_port, :vendor_port, :date_month, :date_day,
:date_hour, :date_minute, :queued, :licenses ].each do |symbol|
t[k] = Integer(v) if k == symbol
end
end
t[:date_dayname] = cal[t[:date_dayname].to_s]
t[:date_year] = clock.year
t[:date_year] = t[:date_year] - 1 if (clock.month < t[:date_month])
t[:since] = sprintf( "%2.2d/%2.2d/%2d-%2.2d:%2.2d", t[:date_day], t[:date_month],
t[:date_year], t[:date_hour], t[:date_minute])
t[:delay_min], t[:delay_string] = Tools.delay( clock, t[:date_year],
t[:date_month], t[:date_day], t[:date_hour], t[:date_minute], 0 )
t[:delay_min] = Integer(t[:delay_min] / 60)
t[:delay_string].chop!.chop!.chop!
# Add a key for a borrowed token.
t.merge!( {:borrow => true} ) if ( /linger/ =~ t[:comment] )
end
# Restore the hash.
{ :user => t }
end
end
###
####
module Tools
def Tools.check_file( file )
return false unless file
if File.exist?(file)
File.file?(file)
else
false
end
end
def Tools.delay( clock = Time.now, year, month, day, hour, minute, second )
delay = clock - Time.local(year.to_i,month.to_i,day.to_i,hour.to_i,minute.to_i, second.to_i)
d = delay.divmod(3600.0*24.0)
h = d[1].divmod(3600.0)
m = h[1].divmod(3600.0)[1].divmod(60.0)
s = m[1].divmod(60.0)[1].divmod(60.0)
[ delay, sprintf("%3.3dj%2.2dh%2.2dmin%2.2ds", d[0], h[0], m[0], s[1].round) ]
end
def Tools.grab_list( list_file, separator = ' ' )
return nil unless Tools.check_file(list_file) && File.stat(list_file).readable?
lines = Array.new
list = Array.new
open(list_file).each_line { |l| lines << l.chomp if l }
# 'split' ignore the multiple '/\s/'.
lines.each { |l| list.concat(l.split(separator)) }
# Suppress the spaces if the separator isn't a "\s".
list.each_index { |i| list[i]= list[i].delete(" ") } unless
list.delete_if { |l| l.length < 1 }
list
end
def Tools.create_output( name_of_file, extension = '', mode = "w" )
begin
file_name = name_of_file + extension
line = __LINE__; File.new( file_name, mode )
rescue Errno::EACCES => error_create
STDERR.puts $PROGRAM_NAME + "(#{line})" +
" ERREUR ! create_output(\"#{file_name}\")"
STDERR.puts $PROGRAM_NAME + "(#{line})" +
" ERREUR ! Message = '#{error_create.message}'"
raise error_create
end
end
end
###
最佳答案
看来您在使用“换行符”时遇到了麻烦。
一个好的指导方针是……* 在规则末尾使用它们(作为终止符)* 如果它们在语义上不是 token 的一部分,则让父规则使用它们。
假设我有一个文档:
A
B
C
我会将其解析为:
#tokens
rule :a do str("A") end
rule :b do str("B") end
rule :c do str("C") end
rule :nl do str("\n") end
# lines
rule :a_line do a>>nl end
rule :b_line do b>>nl end
rule :c_line do c>>nl end
# doc
rule :doc do a_line>>b_line>>nl>>c_line
请注意,“b_line”不会同时使用“\n”,因为它应该对其上下文一无所知。
我还注意到您将“空格”定义为“str(' ').repeat”。这是“str(' ').repeat(0)”的缩写,可以匹配零次。这使得“空间”成为可选的……因此“空间。也许”没有意义。
关于 ruby & Lmstat : parslet and structured multi-line block : where to put the newline statement?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43295971/
这是我第一次在结构中使用结构。我在编译我的程序时遇到了这个错误。错误:字段“结果”的类型不完整。 错误是指这行代码。-->结构result_t结果; 有什么帮助吗? :)谢谢。 typedef str
typedef struct mensagem { int sender ; int receiver ; char *text ; } *Item ; typedef str
我正在使用 ExpressionEngine 和 Structure 附加组件的最新版本。 我正在寻找有关生成 4 项导航栏的帮助,其中两项位于不同的结构级别。 我的结构行如下所示: 服务(父) --
我正在处理一个非常大的数据集。本质上,我将处理数百万条记录并将值存储到数据集中。 每次我存储一个值时,我必须首先检查以确保该值不在数据结构中。如果值在数据结构中,我必须更新(或删除/添加)记录以更新计
我正在尝试分别使用视频帧和音频来分析视频,我想出了一个看起来像这样的模型 现在,我将训练数据分成两个生成器 - 一个用于视频,一个用于音频。我必须进一步将生成器分成两半,我认为这是我遇到错误的地方。因
我有一个创建 N 个进程的程序,每个进程创建 M 个线程。 我还有一个结构需要传递给线程函数。 当我像这样创建 M 个线程时: thread_args_t** thread_arg = malloc(
我正在试图弄清楚如何实现一个等待事件发出信号的函数。指针由DLL函数返回,该函数是存储3个项的结构。其中两个是句柄,它们只是指针,最后是一些随机的未使用的指针。我真的不确定这应该如何格式化,因为我两个
根据PLCOpen、IEC-61131标准,是否可以在声明中初始化结构体? 我正在考虑类似于 this C++ question 的事情. 最佳答案 您可以在结构声明时向结构变量添加默认值。您还可以在
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
在纯 C 中工作,将结构嵌套在其他结构或指向结构的指针中更好。使用指针可以更容易地实现良好的对齐,但是访问内部结构需要额外的取消引用。只是具体地说: typedef struct {
我正在使用 Qt Creator 开发应用程序。 我不是一个好的C++程序员,所以可能会有概念上的错误等。 我在复制结构数组并返回结构时遇到问题。 有很多与类似标题相关的解决方案,但无法解决我的问题。
我正在尝试使用带水印的 dropDuplicate 函数对流数据进行重复数据删除。我目前面临的问题是我必须为给定记录设置两个时间戳 一个是事件时间戳 - 从源创建记录的时间戳。 另一个是传输时间戳 -
很难说出这里问的是什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或言辞激烈,无法以目前的形式合理回答。如需帮助澄清此问题以便可以重新打开,visit the help center . 10年前关
我尝试构建一个嵌套循环,用于创建 2 维零矩阵来解决 LCS 问题(动态规划)。这后来用于计算 Rouge-L 分数(输入是张量,而不是字符串),但它总是出错引发 ValueError: The tw
我曾多次使用 HDFS 和 Kafka,我注意到 Kafka 比 HDFS 更可靠。因此,现在使用 Spark-structured-streaming 时,我很惊讶检查点仅适用于 HDFS。使用 K
C11,6.7.2.1 结构和 union 说明符,约束,3(添加了强调): A structure or union shall not contain a member with incomple
在 emacs lisp 中,各种树结构是常见的。 custom.el通过:type提供论据 defcustom定义自定义变量的预期形状的标准方法。但是有没有一种标准的方法来验证一些随机 emacs
我在网上遇到了以下面试问题。 描述一个数据结构,其中 getValue(int index)、setValue(int index, int value) 和 setAllValues(int val
我正在使用 sqldf 对一个巨大的文件进行子集化。以下命令为我提供了一个 100 行和 42 列的 data.frame。 first <- read.csv.sql("first.txt", se
来自这里的 C++ 背景。我需要为我的一门类(class)编写 C 语言,但我从未接触过这一类(class)。这两个声明之间有什么区别?为什么要包含 struct 关键字?有不同的含义吗?它们在 C+
我是一名优秀的程序员,十分优秀!