use strict; use warnings; my $file = $ARGV[0]; my $s; if (defined $file) { # parse data from file argument open my $fh, '<', $file or die "Failed to open file ($file):$!\n"; # for processing speed, tossing out full line comments and empty lines now while (<$fh>) { next if /^\s*#.*$/ and !/^\s*#\s*base\s*=/; next if /^\s*$/; $s .= $_ } } else { # parse data from DATA while () { next if /^\s*#.*$/ and !/^\s*#\s*base\s*=/; next if /^\s*$/; $s .= $_ } } close $fh or die "Failed to close file ($file): $!\n"; #print STDERR "DATA :\n$s\n"; use Regexp::Grammars; my $parser = qr/ # # \d+(\.\d+)? GlobalPList|LocalPList PList \w+ \[[\w \.,]*\] \d+ \#[^\n]* Pat|Pattern \w+ \w+ \{ \} [\w\.]+ <[global_plist]>+ Version \; \#\s*base\s*=\s*<[base_number]>+ % ,\s*\n \#<[tag]>+ % ,\# <.global_plist_declare> <[plist_option]>* % \s* <.plist_open> ? (<[data_node]> | <.comment>)+ <.plist_close> | | <.reference_plist_declare> ( : | ) ; <.pat_declare> ; ? /xms; $s =~ $parser; use Data::Dumper; open $fh, '>', 'C:\tmp\tmp' or die "FAILED!\n"; print $fh "RESULTS:".Dumper(\%/); print STDERR "RESULTS:".Dumper(\%/); __DATA__ Version 1.0; # Plist SVN Url: $HeadURL: https://XXXXXX... # Plist SVN Revision: $Id: gt.plist 2555 2014-02-06 16:16:26Z vsgatcha $ # RunDir: /XXXXXX... GlobalPList plist1 [option1] [option2] { #base=111 # this is a full line comment Pat n1000000g0000001; # this is a partial line comment Pat n2000000g0000002; #HOT# LocalPList plist2 { Pat n5000000g0000005; GlobalPList plist4 { Pat n8000000g0000008; #KEEP# } } Pat n3000000g0000003; #HOT,COLD# Pat n4000000g0000004; PList plist2; PList file1:plist3; } GlobalPList plist2 [option3] { PList plist1; Pattern n6000000g0000006; Pattern n7000000g0000007; }