Я написал что-то, чтобы сделать именно это.Я не могу понять, как поместить это в metacpan.Тем не менее, я уверен, что там уже лучше, если бы я знал, где искать.Это первое, что я написал на Perl, так что это немного беспорядок.Но в основном вы можете набрать «gettree -l Node interface», и на устройстве XR он вытянет всю конфигурацию."gettree -s Node Description_keyword" будет извлекать все из одного интерфейса конфигурации.Вы также можете использовать его с STDIN, например, "cat file | gettree -l interface".
Программа
#!/usr/bin/perl
use lib '/PATH_TO_Gettree.pm_MODULE/';
use strict;
use warnings;
use Gettree;
use Getopt::Std;
my %opts;
getopts('eislnpm' , \%opts);
my $searchstr;
my $filename;
my $debug=0;
if($ARGV[0]=~m/help/ || $ARGV[0]=~m/^\?$/ )
{ die usage(); }
if($#ARGV<0||$#ARGV>1)
{
usage();
killapp("Please specifiy node and search term, use --help for the help menu");
}
elsif($#ARGV==0)
{
Gettree::setopts( \%opts , \$ARGV[0] );
while(<STDIN>)
{
Gettree::gettree_stream_passline( \$_ );
}
print Gettree::gettree_getreturnstring();
}
else
{
$filename= $ARGV[0];
$filename="/CONFIGS_DIR/".lc $filename if ! $opts{e};
print Gettree::gettree_file ( \%opts , \$filename , \$ARGV[1]) ; #\$filename , $searchstring
}
sub killapp
{
print $_[0]."\n";
exit;
}
sub usage
{
print "
Usage: gettree [OPTION]... [NODE] STRING
Search for PATTERN in each FILE or standard input.
usage gettree <options> <node> <string>
-s include same level
-l include lower levels
-n show line numbers (do not use with STDIN, it wont work)
-i case insensitive
-e exact file location (rather than just the nodename)
-p print parent's same level lines
-m minimal print, do not print parents
Examples:
gettree Node text
gettree -sln NODE CCT_Ref
gettree -l NODE POS8/0
\n\n";
exit;
}
Модуль
#!/usr/bin/perl
package Gettree;
use strict;
use warnings;
my $line;
my $wsdiff = 0;
my $iopt = 0;
my $sopt = 0;
my $lopt = 0;
my $nopt = 0;
my $popt = 0;
my $mopt = 0;
my $linecounter = 0;
my $matched = -1;
my $debug = 0; ##remove later
my @arr;
my @sopt_arr;
my @popt_arr;
my $searchstr;
my $returnstring;
sub setopts # \%opthash , $searchstring
{
cleardata();
push @arr, [ 0, "",0];
my %hash=%{$_[0]};
$iopt = 1 if $hash{i};
$sopt = 1 if $hash{s};
$lopt = 1 if $hash{l};
$nopt = 1 if $hash{n};
$popt = 1 if $hash{p};
$mopt = 1 if $hash{m};
if ( defined $hash{qopts} )
{
$iopt = 1 if $hash{qopts} =~ /i/;
$lopt = 1 if $hash{qopts} =~ /l/;
$nopt = 1 if $hash{qopts} =~ /n/;
$sopt = 1 if $hash{qopts} =~ /s/;
$popt = 1 if $hash{qopts} =~ /p/;
$mopt = 1 if $hash{qopts} =~ /m/;
}
if ( ref($_[1]) ) { $searchstr=$iopt? qr/${$_[1]}/i : qr/${$_[1]}/ ; }
else { $searchstr=$iopt? qr/$_[1]/i : qr/$_[1]/ ; }
}
sub gettree_stream_passline # \$line
{
process_line(${$_[0]});
}
sub gettree_getreturnstring
{
return $returnstring;
}
sub gettree_varable # \%opthash , \$text , $searchstring
{
setopts($_[0] , $_[2]);
my $str=${$_[1]};
while($str=~m#(.*\n)#g)
{
process_line($1);
}
return $returnstring;
}
sub gettree_file # \%opthash , \$filename , $searchstring
{
setopts($_[0] , $_[2]);
my $filename;
if ( ref($_[1]) ) { $filename=${$_[1]}; }
else { $filename=$_[1] ; }
open FH, "<", $filename or die "\nFile ".$filename." cannot be found\nerror : ".$!."\n";
while(my $text=<FH>)
{
process_line($text);
}
close FH;
return $returnstring;
}
sub process_line
{
$line=shift;
if($line=~m/^([ \t]+)/) { $wsdiff=length($1) }
else { $wsdiff=0 };
if($wsdiff>$arr[$#arr][0])
{
push @arr, [ $wsdiff , $line , $linecounter ];
if ( $sopt || $popt )
{
@popt_arr=@sopt_arr if $popt;
@sopt_arr=() if defined $sopt_arr[0];
}
}
else
{
while( @arr && $arr[$#arr][0]>$wsdiff )
{
pop @arr;
@sopt_arr=@popt_arr if ( $sopt || $popt );
@popt_arr=() if $popt;
}
if($#arr<0)
{
push @arr, [ $wsdiff , $line, $linecounter ];
}
else
{
push @sopt_arr, $arr[$#arr] if $sopt || $popt ;
$arr[$#arr]=[ $wsdiff , $line , $linecounter ];
}
}
@sopt_arr=() if $#sopt_arr>200; ## to avoid filling the memory
@popt_arr=() if $#popt_arr>200; ## to avoid filling the memory
##used in l and s opts to print lines after match
if($matched>=0)
{
if($wsdiff>$matched)
{
printline(\$line) if $lopt==1 ;
}
elsif ($wsdiff<$matched)
{
$matched=-1;
}
else
{
if ($sopt )
{ printline(\$line) }
else
{ $matched=-1 }
}
}
if( $matched==-1 && $line=~m/$searchstr/ )
{
printtree();
$matched=$wsdiff if $sopt || $lopt;
}
$linecounter++;
}
sub printtree
{
if(!$mopt)
{
for (0..$#arr-(1+$popt))
{
printline( \$arr[$_][1] , \$arr[$_][2] );
}
}
if($popt)
{
for (0..$#popt_arr)
{
printline( \$popt_arr[$_][1] , \$popt_arr[$_][2] );
}
printline( \$arr[$#arr-1][1] , \$arr[$#arr-1][2] ); #print the parent
@popt_arr=() ;
}
if($sopt)
{
for (0..$#sopt_arr)
{
printline( \$sopt_arr[$_][1] , \$sopt_arr[$_][2] );
}
@sopt_arr=() ;
}
printline( \$arr[$#arr][1] , \$arr[$#arr][2] );
@arr=();
push @arr, [ $wsdiff , $line , $linecounter ];
}
sub printline
{
$nopt==1? $returnstring.= ${$_[1]}+1 ." : ".${$_[0]} : $returnstring.= ${$_[0]};
}
sub cleardata
{
$line="";
$wsdiff = 0;
$iopt = 0;
$sopt = 0;
$lopt = 0;
$nopt = 0;
$popt = 0;
$mopt = 0;
$linecounter = 0;
$matched = -1;
@arr=();
@sopt_arr=();
@popt_arr=();
$searchstr="";
$returnstring="";
}
1;
Краткое объяснение, как это работает Программа представляет собой просто ссылку на модуль.Я модуль, потому что я использовал его во многих программах и в одиночку.Gettree.pm будет отправлять данные построчно в process_line ().строка процесса получит пробел ($ wsdiff) и будет использовать его как маркер.любая строка непосредственно перед приращением пробела будет сохранена в @arr.для печати, если совпадение найдено позже.так что родитель хранится.@sopt_arr - для той же строки, поэтому в ней хранятся предыдущие строки того же пробела.@popt_arr - для родительского соответствия, но это не очень хорошо работает (я действительно не использую его, его можно удалить).когда сопоставление для строки поиска выполнено, печатаются @ arr, Sopt_arr и & @popt_arr, устанавливается $ matched, это будет использоваться для опции -l.все строки после совпадения печатаются до тех пор, пока пробел не станет <совпадающим пробелом.Итак, в итоге, каждый прирост будет занимать каждый уникальный пробел.это работает для Juniper и Alcatel тоже.Я уверен, что это будет работать и на других.</p>
не забудьте изменить CONFIGS_DIR и PATH_TO_Gettree.pm_MODULE, чтобы они соответствовали путям вашей файловой системы