Flexlm/Flexnet 라이센스 서비스를 보유하고 있으며이 서비스의 출력을 분석하고 싶습니다. 모든 출력은 멀티 라인의 구조화 된 블록입니다. 내 첫 번째 단계는 lmutil lmstat -c <[email protected]> -a
의 출력을 구문 분석하여 라이센스 및 증분을 사용하는 것입니다.Ruby & Lmstat : parslet 및 구조화 된 멀티 라인 블록 : 어디에서 개행 명령문을 넣을까요?
Ruby와 Parslet을 사용하려고합니다. 모든 라인은 개별적으로 잘 분석됩니다. 특정 유형의 라인 반복을 구문 분석하는 규칙이 있지만 구조화 된 블록 블록을 구문 분석 할 수 없습니다.
저는 '줄 바꿈'구문을 여러 줄짜리 구조화 된 블록에 넣을 위치를 정의하는 법칙 ('규칙'보다이 문맥에서 가장 좋은 단어)을 찾고 있습니다.
저는 Debian Jessie (stable/x86_64)와 Ruby 2.1.5p273 및 Parslet 1.6.1-1로 작업했습니다.
나는 저자에게 연락했으나 미안하지만 그는 나를 도울 시간이 부족합니다. 본 웹 페이지는 다음과 같습니다
- URL : www.viget.com/articles/write-you-a-parser-for-fun-and-win
- URL : jmettraux.wordpress.com/2011/05/11/parslet 앤 JSON/
- 재귀 하강 파서 (칼레) - 비디오
- Wicked Good Ruby 2013 - Writing DSL's with Parslet by Jason Garber - Video
- 여러 줄 방법 체인 포함 된 블록에 대한 적절한 루비 스타일 - 유래
- 루비 parslet : 여러 줄을 구문 분석 - StackOverFlow
- Parslet을 사용하여 Ruby에서 C 스타일 주석을 처리하는 방법은 무엇입니까? - StackOverFlow
여러 줄로 구성된 구조적 블록의 규칙을 구성하는 방법을 이해하려고 많은 시간을 보냈습니다. 아래에는 모든 테스트 문자열과 출력이 포함 된 소스 코드가 있습니다.
내 접근 방식은 구축하는 것입니다 :
- 초등학교 규칙을 라인의 조각을 구문 분석
- '줄 바꿈'문없이 전체 라인을 구문 분석하는 규칙;
- 사용 된 토큰에 대한 행과 같이 동일한 유형의 정보의 반복을 구문 분석하는 규칙.
- 데이터 그룹을 구문 분석하는 규칙입니다. header + lines of repetitions;
- 그룹의 반복을 구문 분석하는 규칙입니다.
3 점이 확실하지 않으며 '4'와 '5'로 완전히 잃어 버렸습니다.
미리 도움을 청하십시오.
[UPDATE - 2017년 4월 29일 :
#!/usr/bin/env ruby
# This code try to parse the output of 'lmutil lmstat -c <[email protected]> -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
출력 [기능 버전을 넣어 제거 2017년 7월 13일]를 [2017년 7월 14일 코드의 일부는 제거되었다] - Problem solved] Nigel Thorne에게 감사의 말을 전합니다. 문제가 해결되었습니다.당신의 충고에 따라 '공간'에 대한 규칙을 수정했습니다.
[07/13/2014 : 일부 기능을 제거하려면 일부 텍스트를 삭제하십시오. ]
[UPDATE - 2017년 7월 13일 - 응용 프로그램을 테스트 할 수있는 분석]
나는 루비와 Parslet와 lmstat의 출력의 구문 분석을 테스트 할 수있는 응용 프로그램을 완료했습니다. 구문 분석은 각 편집기에 따라 다르므로 일부 경우는 다룰 수 없지만 30 개 이상의 라이센스 서비스를 사용하여 구문 분석의 유효성을 검사합니다.
- parse_lmstat.rb : 도움을 가지고 사용 './parse_lmstat --help'
나는 3 개 개의 파일을 줄 수 있습니다. 구문 분석을 테스트하는 응용 프로그램입니다.
- readstdin_lmstat.rb : YAML 형식으로 생성 된 구문 분석 된 lmstat의 출력을 STDIN에서 읽습니다.
- display_lmstat.rb : 데이터에서 액세스하는 방법을 보여 주며 구문 분석의 구조를 개선하는 데 사용되었습니다. 스크립트는 단순히
irb
세션보다 좋습니다. 그것은 STDIN에서 구문 분석 된 lmstat의 출력을 YAML 형식으로 읽습니다.
예 : 알려진
~/bin/lmutil lmstat -a -c [email protected] | ./parse_lmstat.rb --screen | ./display_lmstat.rb
한 버그 : A [CTRL-C]이 신호 할 때 잘 갇혀되지 않는 것 같다 루비 경우에 일부 오류 메시지를 보냅니다.
이제 라이선스 서버를 선택하고 데이터를 표시 할 작은 WEB 응용 프로그램 (SINATRA?)을 갖고 싶지만 HTML 또는 CSS를 말할 수는 없습니다 ... 어떤 도움도 감사하겠습니다 ;-)
아래와 같이 은 30000 자로 제한되어 있으므로 클래스 만 구문 분석하고 lmstat의 출력을 변환 할 수 있습니다.
#!/usr/bin/env ruby
#
# class_lmstat.rb
#
# This code try to parse the output of 'lmutil lmstat -c <[email protected]> -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: [email protected]
# 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
###
왜 모든 개행 문을 정리하여 통일되게 만드십니까 – Tsao
Hello Tsao, 죄송합니다. 영어가 모국어가 아니므로, 무슨 뜻인지 이해가되지 않습니다. 당신의 발언을 발전시킬 수 있습니까? 감사. – Scapin
새 질문을 열어야합니다 ...이 질문을 확장하지 마십시오. (또는 사람들은 질문에 대한 좋은 답변을 찾기 위해 사이트를 사용할 수 없습니다.) –