3

我必须解析很多 UNIX CLI 输出,大多数时候,输出是一个表,但它们的列数/格式总是不同的......等等,我必须不断修改每个命令的解析代码。TxtFSM 让生活变得轻松,但我仍然需要编写模板。

我想编写一个脚本来自动检测 CLI 输出,当它检测到一个表时,它会解析它。作为解析世界的新手,我想知道这有多难/复杂?如果有人以前见过类似的努力/项目?

我总是对 BNF、YACC 等高级解析主题感到困惑

谢谢

4

1 回答 1

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'
                ]
            ]
        ]
    ]
于 2015-08-16T15:45:31.373 回答