Автоматическое обнаружение / синтаксический анализ таблиц в Python
Я должен проанализировать большую часть вывода CLI UNIX, в большинстве случаев вывод представляет собой таблицу, но они всегда различаются по количеству столбцов / формату... и т. Д., Я должен продолжать изменять свой код синтаксического анализа для каждой команды. TxtFSM облегчает жизнь, но мне все еще нужно написать шаблон.
Я хотел бы написать сценарий, который будет автоматически определять вывод CLI, и когда он обнаруживает таблицу, он будет анализировать его. Интересно, как новичку в мире парсинга, насколько это сложно / сложно? Если кто-нибудь видел подобные усилия / проекты раньше?
Меня всегда смущают сложные темы разбора, такие как BNF, YACC... и т. Д.
Спасибо
1 ответ
Вот как вы можете разобрать df
вывод в таблицу с использованием Perl и Marpa::R2
сценарий (~
обозначает лексические правила):
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'
]
]
]
]