ararghat has asked for the wisdom of the Perl Monks concerning the following question:

p> Hi Dears, I am beginner so please explain in simple way

I want to extract elements behind first ) & between ) and ;; {or extract parameter and variables}

from the given and for the nested case file (or repeat the process if any case is coming)

I need two type of solution : 1.using simple code 2.using subroutine

input.txt abhi) old_file="ak.csv" datefile="ak_nt_$curr_date.csv" cat /aksin/nil; cat /home/null case `kumar` in dbk) newwack="rac_client_$curr_date.ack" IN_DIR="class/5060" ;; src) src_folder="class/5061 ;; esac echo "$date_file" ;; bill)old_file="abh_cash.csv" date_file="ods_nt_cash_acc_$curr_date.csv" newwack="rac_cash_acc_$curr_date.ack" IN_DIR="xyx\5060" ;; payu) old_file="ods_ven.csv" newfile="ods_nt_ven_$curr_date.csv" newwack="rac_vendor_$curr_date.ack" IN_DIR="ofc\5060" case para in bcc) newreck="client_$curr_simul.ack" IN_DIR="class/5062" ;; src1) src_folder="class/5061 ;; esac ;; ##########################

OUTPUT should be : abhi: old_file="ak.csv" abhi: datefile="ak_nt_$curr_date.csv" abhi:dbk: newwack="rac_client_$curr_date.ack" abhi:dbk: IN_DIR="class/5060" abhi:src: src_folder="class/5061 bill: old_file="abh_cash.csv" bill: date_file="ods_nt_cash_acc_$curr_date.csv" bill: newwack="rac_cash_acc_$curr_date.ack" bill: IN_DIR="xyx\5060" payu: old_file="ods_ven.csv" payu: newfile="ods_nt_ven_$curr_date.csv" payu: newwack="rac_vendor_$curr_date.ack" payu: IN_DIR="gunda\5060" payu:bcc: newreck="client_$curr_simul.ack" payu:bcc: IN_DIR="class/5062" payu:src1: src_folder="class/5061

please provide me solution. my modified code (Previously given by a perl monk for approximately simillar situation ) is given below which is not working properly.

open (data, "<input.txt"); while (<data>) { s/^\s+//g; #LTRIM if (/"(.*)"\)(.*)$/) { #pattern match $parameter = $1; $var = $2 . "\n"; } else { $var = $_; } if (/case/../esac/){ if (/"(.*)"\)(.*)$/) { $parameter ="$parameter:$1"; $var = $2 . "\n"; } } if (/;;/) { print "\n"; next; } if($var=~/^\s*$/) {next;} #if $var is empty or 1 or more than 1 + whitespaces. elsif ($var!~/=/) {next;} #ignore if $var does not consist "=" +sign else{ print "$parameter: $var"; } } close data;

Replies are listed 'Best First'.
Re: extract content for nested pattern in a file
by choroba (Cardinal) on Oct 04, 2016 at 16:25 UTC
    > please explain in simple way

    Can't be simper! Just write a parser for the input format.

    (I had to add the missing double quotes at lines 14 and 38.)

    #!/usr/bin/perl use warnings; use strict; use feature qw{ say }; use Marpa::R2; my $dsl = << '__DSL__'; :default ::= action => ::first lexeme default = latm => 1 Block ::= Outer Block action => append | Outer Outer ::= Header Body (semi2) action => keyval || Header Body action => keyval Header ::= varname (rpar) Body ::= Assignment action => expand | Assignment Body action => append | Inner | Inner Body action => append | (Garbage) action => [] | (Garbage) Body InBody ::= Assignment action => expand | Assignment InBody action => append | (Garbage) action => [] | (Garbage) InBody Assignment ::= varname (eq) Quoted action => assign Quoted ::= (quote) string (quote) action => quoted Inner ::= Header InBody (semi2) action => keyval Garbage ::= Cat | Case | Esac | Echo Cat ::= cat path | cat path semi1 Case ::= case What in Esac ::= esac Echo ::= echo Quoted What ::= varname | bq varname bq :discard ~ whitespace whitespace ~ [\s]+ varname ~ [\w]+ string ~ [\w.$/\\]+ quote ~ '"' semi1 ~ ';' semi2 ~ ';;' eq ~ '=' rpar ~ ')' path ~ [\w/]+ cat ~ 'cat' case ~ 'case' in ~ 'in' bq ~ '`' esac ~ 'esac' echo ~ 'echo' __DSL__ sub quoted { qq("$_[1]") } sub assign { [ @_[1, 2] ] } sub append { [ $_[1], 'ARRAY' eq ref $_[2] ? @{ $_[2] } : $_[2] ] } sub keyval { +{ $_[1] => $_[2] } } sub expand { [ $_[1] ] } sub addkey { +{ %{ $_[1] }, %{ $_[2] } } } my $grammar = 'Marpa::R2::Scanless::G'->new({ source => \$dsl }); open my $IN, '<', shift or die $!; my $input = do { local $/; <$IN> }; my $parsed = ${ $grammar->parse(\$input, 'main') }; for my $h (@$parsed) { my $key = (keys %$h)[0]; for my $val (@{ $h->{$key} }) { { ARRAY => sub { say join ': ', $key, join '=', @$val }, HASH => sub { output_hash($key, $val) }, }->{ ref $val }->(); } } sub output_hash { my ($key, $val) = @_; say for map { join ': ', $key, $_ } map { my $k = $_; map { "$k: " . join '=', @$_ } @{ $val->{$k} } } keys %$val; }

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: extract content for nested pattern in a file
by ww (Archbishop) on Oct 04, 2016 at 11:49 UTC
    1. Smells like homework. If so, say so.
    2. "... which is not working properly." So, what is it doing wrong (detailed explanation, please, including verbatim messages)?
    Questions containing the words "doesn't work" (or their moral equivalent) will usually get a downvote from me unless accompanied by:
    1. code
    2. verbatim error and/or warning messages
    3. a coherent explanation of what "doesn't work actually means.
Re: extract content for nested pattern in a file
by neilwatson (Priest) on Oct 04, 2016 at 15:10 UTC
Re: extract content for nested pattern in a file
by tybalt89 (Monsignor) on Oct 04, 2016 at 17:25 UTC

    > please explain in simple way

    Can't be simpler! Just write a parser for the input format.

    #!/usr/bin/perl # http://perlmonks.org/?node_id=1173242 use strict; use warnings; my @header; while(<DATA>) { local $" = ':'; 1 while /\G\s*(\w+)\)/gc ? push @header, $1 : # name) /\G\s*(\w+=\S+)/gc ? print "@header: $1\n" : # parameter=value /\G\s*;;/gc && (pop @header, @header || print "\n"); # end } __DATA__ abhi) old_file="ak.csv" datefile="ak_nt_$curr_date.csv" cat /aksin/nil; cat /home/null case `kumar` in dbk) newwack="rac_client_$curr_date.ack" IN_DIR="class/5060" ;; src) src_folder="class/5061 ;; esac echo "$date_file" ;; bill)old_file="abh_cash.csv" date_file="ods_nt_cash_acc_$curr_date.csv" newwack="rac_cash_acc_$curr_date.ack" IN_DIR="xyx\5060" ;; payu) old_file="ods_ven.csv" newfile="ods_nt_ven_$curr_date.csv" newwack="rac_vendor_$curr_date.ack" IN_DIR="ofc\5060" case para in bcc) newreck="client_$curr_simul.ack" IN_DIR="class/5062" ;; src1) src_folder="class/5061 ;; esac ;;
Re: extract content for nested pattern in a file
by tybalt89 (Monsignor) on Oct 04, 2016 at 22:20 UTC

    Hehehe

    #!/usr/bin/perl # http://perlmonks.org/?node_id=1173242 use strict; use warnings; my @header; ($", $/) = ':'; print <DATA> =~ s/ \s+ (?{ '' }) | (\w+)\) (?{ !push @header, $1 }) | (\w+=\S+) (?{ "@header: $2\n" }) | ;; (?{ pop @header; !@header && "\n" }) | \S+ (?{ '' }) /$^R/grx; __DATA__ abhi) old_file="ak.csv" datefile="ak_nt_$curr_date.csv" cat /aksin/nil; cat /home/null case `kumar` in dbk) newwack="rac_client_$curr_date.ack" IN_DIR="class/5060" ;; src) src_folder="class/5061 ;; esac echo "$date_file" ;; bill)old_file="abh_cash.csv" date_file="ods_nt_cash_acc_$curr_date.csv" newwack="rac_cash_acc_$curr_date.ack" IN_DIR="xyx\5060" ;; payu) old_file="ods_ven.csv" newfile="ods_nt_ven_$curr_date.csv" newwack="rac_vendor_$curr_date.ack" IN_DIR="ofc\5060" case para in bcc) newreck="client_$curr_simul.ack" IN_DIR="class/5062" ;; src1) src_folder="class/5061 ;; esac ;;