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

__DATA__ x# x' x( x$ x) bxxx * x" x% x& $end $dumpoff $end #3537871350 $dumpon $end 0& 0% 0$ b01 + 0! 0( 0# 1' 0" z) b111 * #3537876550 1! #3537881760 0! #3537886970 1! #3537892180 0!

How do I extract text from #3537871350 to #3537876550 Thanks!! following is my code

__CODE__ open my $fh, "sample.vcd" or die $!; my $fields_t0=0; my @fields_mod=(); my $re = qr{\$dumpoff \$end(\#[\d]+)\$dumpon \$end(.*)\#[\d]+}s; #open $fh; { my $i=0; local $/ = ""; while (<$fh>) { if (/$re/) { $fields_t0 = $1 ; say "match!!"; @fields_mod = split /\s+/ , $2; } } } say $fields_t0; foreach my $field (@fields_mod) { say $field; }

Replies are listed 'Best First'.
Re: extract text from multi-line context (Verilog::VCD)
by toolic (Bishop) on Aug 15, 2014 at 12:30 UTC
    Verilog::VCD can parse a VCD file. If you post the header portion of your input file and your desired output, I can provide further assistance.

      following is the vcd file header

      $date Fri Aug 1 17:33:57 2014 $end $version ncsim 08.20-s012 $end $timescale 1ps $end $scope module system $end $scope module soc $end $scope module newton_analog_atop $end $var wire 1 ! BBPLL_CLKO_DIG_96M $end $var wire 1 " CKO_HFOSC_2DIV12 $end $var wire 1 # CLKO_RXADC_96M $end $var wire 1 $ VBGOK_H $end $var wire 1 % YOUT_RC_CAL $end $var wire 1 & YOUT_RC_CAL_PGA $end $var wire 1 ' ABB_BIAS_EN $end $var wire 1 ( TXMIX_EN $end $var wire 1 ) XO32K_VCOUT $end $var wire 3 * AGC_IF_CAP [2:0] $end $var wire 2 + BBAGC_AVWIN [1:0] $end $upscope $end $upscope $end $upscope $end $scope module system $end $scope module soc $end $scope module newton_analog_atop $end $var wire 3 * AGC_IF_CAP [2:0] $end $var wire 2 + BBAGC_AVWIN [1:0] $end $upscope $end $upscope $end $upscope $end $enddefinitions $end $dumpvars x! bxx + x# x' x( x$ x) bxxx * x" x% x& $end $dumpoff $end

      I want to produce following result

      V0 (BBPLL_CLKO_DIG_96M 0) vsource type=pwl wave=[ 0p 0 199p 0 200p VDD +/2 399p VDD/2 400p 0 599p 0 600p VDD/2 ...... ] V1 (CKO_HFOSC_2DIV12 0) vsource type=pwl wave=[0p 0] V2 (CLKO_RXADC_96M 0) vsource type=pwl wave=[0p 0] V3 (VBGOK_H 0) vsource type=pwl wave=[0p 0] V4 (YOUT_RC_CAL 0) vsource type=pwl wave=[0p 0] V5 (YOUT_RC_CAL_PGA 0) vsource type=pwl wave=[0p 0] V6 (ABB_BIAS_EN 0) vsource type=pwl wave=[0p VDD/2] V7 (TXMIX_EN 0) vsource type=pwl wave=[0p 0] V8 (XO32K_VCOUT 0) vsource type=pwl wave=[0p z] V9 (AGC_IF_CAP\<0\> 0) vsource type=pwl wave=[0p VDD/2] V10 (AGC_IF_CAP\<1\> 0) vsource type=pwl wave=[0p VDD/2] V11 (AGC_IF_CAP\<2\> 0) vsource type=pwl wave=[0p VDD/2] V12 (BBAGC_AVWIN\<0\> 0) vsource type=pwl wave=[0p 0] V13 (BBAGC_AVWIN\<1\> 0) vsource type=pwl wave=[0p VDD/2]
        I pieced together your 2 VCD file fragments, and I created some code which will parse the file:
        use warnings; use strict; use Verilog::VCD qw(:all); my $vcd= parse_vcd('sample.vcd'); for my $code (keys %{ $vcd }) { for my $net (@{ $vcd->{$code}->{nets} }) { print "$net->{name}\n"; for my $aref (@{ $vcd->{$code}{tv} }) { print "@{ $aref }\n"; } } }

        It seems like you really only need the signal names, not the times or logic values (except for maybe your BBPLL_CLKO_DIG_96M signal?). Parsing this way gives you all the info you need. You just need to format it the way you want.

        It's odd that your VCD file header declares some signals (such as AGC_IF_CAP[2:0]) multiple times. It seems unnecessary.

Re: extract text from multi-line context
by Anonymous Monk on Aug 15, 2014 at 09:07 UTC

    Well, your regex doesn't mention newlines :/)
    your data has newlines
    all that dumpoff stuff has newlines in between
    its like whitespace :)
    add that ( [\r\n ]+ ) to your pattern

    And quotemeta

    use Path::Tiny qw/ path /; my $raw = path( $file )->slurp_raw; my $re = qr{ \Q$dumpoff $end\E [\r\n ]+ (\#[\d]+) [\r\n ]+ \Q$dumpon $end\E [\r\n ]+ (.*?) \#[\d]+ }sx; while( $raw =~ m/$re/g ){ my( $id, $tidy ) = ( $1, $2 ); ... }
      my $raw = path( sample.vcd)->slurp_raw; my $re = qr{ \Q$dumpoff $end\E [\r\n ]+ (\#[\d]+) [\r\n ]+ \Q$dumpon $end\E [\r\n ]+ (.*?) \#[\d]+ }sx; while( $raw =~ m/$re/g ){ my( $id, $tidy ) = ( $1, $2 ); say $i; say $2; }

      has following error, please help!!

      Global symbol "$dumpoff" requires explicit package name at ./vcd2net.p +l line 8. Global symbol "$end" requires explicit package name at ./vcd2net.pl li +ne 8. Global symbol "$dumpon" requires explicit package name at ./vcd2net.pl + line 8. Global symbol "$end" requires explicit package name at ./vcd2net.pl li +ne 8. Global symbol "$i" requires explicit package name at ./vcd2net.pl line + 21. Bareword "sample" not allowed while "strict subs" in use at ./vcd2net. +pl line 7. Bareword "vcd" not allowed while "strict subs" in use at ./vcd2net.pl +line 7. Execution of ./vcd2net.pl aborted due to compilation errors (#1) (F) You've said "use strict" or "use strict vars", which indicates + that all variables must either be lexically scoped (using "my" or +"state"), declared beforehand using "our", or explicitly qualified to say which package the global variable is in (using "::").

        has following error, please help!!

        *cough* thats what heppens when you edit in textbox late at night :)

        for the first part simply use what you had before  \$dumpoff \$end instead of "\Q\E"

        For the other part, $1 is not $i :)

        And the other part, you must quote your strings,

        add use diagnostics; to get more verbose explanations

Re: extract text from multi-line context
by kbrannen (Beadle) on Aug 15, 2014 at 17:10 UTC
    If I understand your question, you want all lines between markers. If so, you need the "flip-flop" operator, otherwise known as ".." in list context. You can search for it's use and examples here on perlmonks or goto http://perldoc.perl.org/perlop.html and search for that phrase there. It's not something I use very often, but when I do need it then it's very nice to have. :) HTH, Kevin