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

I am trying to grab the comments from a config file... I want to lookup a specific "key=" entry and find all comments above it (I can ensure that there is a blank line to separate them...)
I know what I want to do in english, but can't get a regex to do it...any help is appreciated ;-)
my $g=<<'_END_'; ## START # comment 1 # 2 # 3 # 4 key1=val1 # info a # b # c # d # e key2=val2 # comment ! # @ # # key3=val3 _END_ my $id = 'key3'; my ($ret) = $g =~ m/(.*)(?!\n\s*\n)\n$id/s; print $ret;

Replies are listed 'Best First'.
Re: multi-line regex match quest
by sauoq (Abbot) on Sep 29, 2002 at 05:20 UTC
    $ret = $1 if $g =~ /\n\s*\n((?m:^#.*\n)+)$id/;
    -sauoq
    "My two cents aren't worth a dime.";
    
      AWESOME AWESOME AWESOME
      thanks thanks thanks
      (I only understand it about 50% so far...)
        (I only understand it about 50% so far...)

        Well let me see if I can shed some light.

        $ret = $1 if $g =~ /\n\s*\n((?m:^#.*\n)+)$id/;
        The first bit is obviously just assigning $1 to $ret if the pattern matches. That's the easy part. Now let's look at the pattern.
        /\n\s*\n # This matches your blank line between comments. ( # Capture into $1. (?m: # Don't capture, but match this group as multiline. Wh +ich means match '^' and '$' # at the beginning or end of any line in the string. ^# # Match the comment delimiter at the start of a line. .*\n # Match everything up to, and including, the newline a +t the end of a line. )+ # Match this group one or more times. ) # End of $1 capture. $id # This is the key you're looking for. /x
        Very well done. sauoq++

        kelan


        Yak it up with Fullscreen ChatBox

Re: multi-line regex match quest
by BrowserUk (Patriarch) on Sep 29, 2002 at 05:02 UTC

    It ain't pretty, but using the sexeger (reverse regex) technique, which can no doubt be implemented better, this works.

    It requires you start with your lines in an unchomped array rather than a single line though.

    my @g=<DATA>; my $id = 'key3'; my $g = join'',reverse @g; if (my ($ret) = $g =~ m/^$id=.*?\n(.*?)\n\n/s) { $ret = join$/,reverse split$/,$ret; print $ret; } else { print 'Failed!'.$/; } __DATA__ ## START # comment 1 # 2 # 3 # 4 key1=val1 # info a # b # c # d # e key2=val2 # comment ! # @ # # key3=val3

    Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!
      Did you ever consider using Config::IniFiles ?
      Could save you a lot of time..