我不得不解析很多UNIX CLI输出,大多数时候,输出是一个表,但它们总是在列数/格式上有所不同…等等,我必须不断修改每个命令的解析代码。TxtFSM使生活变得简单,但我仍然需要编写模板。
我想写一个脚本,将自动检测CLI输出,当它检测到一个表,它将解析它。作为解析世界的新手,我想知道这有多难/复杂吗?是否有人以前见过类似的努力/项目?
我总是混淆高级解析主题,如BNF, YACC…等
谢谢
下面是如何使用perl和Marpa将df
输出解析为表::R2
script (~
表示词法规则):
use 5.010;
use strict;
use warnings;
use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Terse = 1;
$Data::Dumper::Deepcopy = 1;
use Marpa::R2;
my $g = Marpa::R2::Scanless::G->new( { source => (<<'END_OF_SOURCE'),
:default ::= action => [ name, value]
lexeme default = action => [ name, value] latm => 1
table ::= (header [n]) rows
header ~ 'Filesystem Size Used Avail Use% Mounted on'
rows ::= row+ separator => [n]
row ::= fs size used avail use_percent mounted_on
fs ~ [A-Z] ':'
size ~ digits 'G'
used ~ digits 'G'
avail ~ digits 'G'
use_percent ~ digits '%'
mounted_on ~ [/w]+
digits ~ [d.]+
:discard ~ whitespace
whitespace ~ [s]+
END_OF_SOURCE
} );
my $input = <<EOI;
Filesystem Size Used Avail Use% Mounted on
C: 101G 90G 11G 90% /cygdrive/c
D: 366G 230G 137G 63% /cygdrive/d
E: 38G 9.6G 28G 26% /cygdrive/e
EOI
say Dumper $g->parse( $input, { trace_terminals => 0 } ); exit;
输出:[
'table',
[
'rows',
[
'row',
[
'fs',
'C:'
],
[
'size',
'101G'
],
[
'used',
'90G'
],
[
'avail',
'11G'
],
[
'use_percent',
'90%'
],
[
'mounted_on',
'/cygdrive/c'
]
],
[
'row',
[
'fs',
'D:'
],
[
'size',
'366G'
],
[
'used',
'230G'
],
[
'avail',
'137G'
],
[
'use_percent',
'63%'
],
[
'mounted_on',
'/cygdrive/d'
]
],
[
'row',
[
'fs',
'E:'
],
[
'size',
'38G'
],
[
'used',
'9.6G'
],
[
'avail',
'28G'
],
[
'use_percent',
'26%'
],
[
'mounted_on',
'/cygdrive/e'
]
]
]
]