Can I Grep multiple lines??

Discussion in 'Perl Misc' started by Chris L., Feb 10, 2006.

  1. Chris L.

    Chris L. Guest

    Dear All,
    I am trying to match a specific pattern using grep.

    my @results=grep(/$cominput/,@common);
    print "@results";

    Naturally,Grep is only printing the lines that variable '$cominput' is
    found on. My dilemma is I want to print a pattern. Specifically, where
    variable '$cominput' is found all the way until the character '<' is
    found. Example,

    <$cominput 7894596 isnlpop 78304 plmeitn 4457624 knmljebn
    93643456346500 lfnsndh 235 hfgnsdljjtngf 7753 fhs 8694039486 jfsndfkgs
    jsdhfnskdk 753299658 hgnsnd 2573275 nvndjgfi 847523
    <
    I would like to grep from "$cominput" to the character "<".

    I have looked into the map function and several pattern matching
    examples from google searches, ie:
    while (<>) {
    if (/BEGIN PATTERN/ .. /END PATTERN/) {
    }
    }

    But nothing seems to be working. is there a better way to accomplish
    this??
    Thank you very much for your time.
    Chris
     
    Chris L., Feb 10, 2006
    #1
    1. Advertising

  2. Chris L.

    Guest

    Chris L. wrote:
    > I am trying to match a specific pattern using grep.
    >
    > I would like to grep from "$cominput" to the character "<".
    >
    > I have looked into the map function


    You need to instead look at how Regular Expressions work (perldoc
    perlre), such as (untested):

    grep /$cominput.*</ @whatever;

    --
    http://DavidFilmer.com
     
    , Feb 10, 2006
    #2
    1. Advertising

  3. Chris L.

    Guest

    wrote:
    > grep /$cominput.*</ @whatever;


    Waitaminute, that didn't answer the question - sorry. Too late I
    noticed the OP specified multiple lines.

    I don't believe you can grep over multiple lines, but I'm not certian
    of that...

    --
    http://DavidFilmer.com
     
    , Feb 10, 2006
    #3
  4. Just a minor tweak to your regex:

    Jim Gibson <> writes:
    > #!/usr/local/bin/perl
    > use strict;
    > use warnings;
    >
    > local $/;
    > my $data = <DATA>;
    > if( $data =~ m/<\$cominput(.*)</s ) {


    You probably want:

    if( $data =~ m/<\$cominput([^<]*)</s ) {

    there instead. Try running both versions against a __DATA__ section
    that looks like:

    <$cominput 7894596 isnlpop 78304 plmeitn 4457624 knmljebn
    93643456346500 lfnsndh 235 hfgnsdljjtngf 7753 fhs 8694039486 jfsndfkgs
    jsdhfnskdk 753299658 hgnsnd 2573275 nvndjgfi 847523
    <
    <$cominput 7894596 isnlpop 78304 plmeitn 4457624 knmljebn
    93643456346500 lfnsndh 235 hfgnsdljjtngf 7753 fhs 8694039486 jfsndfkgs
    jsdhfnskdk 753299658 hgnsnd 2573275 nvndjgfi 847523
    <

    and see why. :)

    -=Eric
     
    Eric Schwartz, Feb 10, 2006
    #4
  5. Chris L. wrote:
    > Dear All,
    > I am trying to match a specific pattern using grep.
    >
    > my @results=grep(/$cominput/,@common);
    > print "@results";
    >
    > Naturally,Grep is only printing the lines that variable '$cominput' is
    > found on. My dilemma is I want to print a pattern. Specifically, where
    > variable '$cominput' is found all the way until the character '<' is
    > found. Example,
    >
    > <$cominput 7894596 isnlpop 78304 plmeitn 4457624 knmljebn
    > 93643456346500 lfnsndh 235 hfgnsdljjtngf 7753 fhs 8694039486 jfsndfkgs
    > jsdhfnskdk 753299658 hgnsnd 2573275 nvndjgfi 847523
    > <
    > I would like to grep from "$cominput" to the character "<".
    >
    > I have looked into the map function and several pattern matching
    > examples from google searches, ie:
    > while (<>) {
    > if (/BEGIN PATTERN/ .. /END PATTERN/) {
    > }
    > }
    >
    > But nothing seems to be working. is there a better way to accomplish
    > this??


    if i understand your problem correctly, this may work:
    while (<>) {
    /($cominput[^<]*?)</ && print $1, "\n";
    }
     
    it_says_BALLS_on_your forehead, Feb 10, 2006
    #5
  6. Chris L.

    Guest

    "Chris L." <> wrote:
    > Dear All,
    > I am trying to match a specific pattern using grep.
    >
    > my @results=grep(/$cominput/,@common);
    > print "@results";
    >
    > Naturally,Grep is only printing the lines that variable '$cominput' is
    > found on.


    It is returning lines that match the *contents* of variable $cominput when
    such contents are interpreted as a regex.


    > My dilemma is I want to print a pattern. Specifically, where
    > variable '$cominput' is found all the way until the character '<' is
    > found. Example,


    Then change the definition of a line such that they are terminated by "<"
    rather than by "\n".

    $/='<';

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Feb 10, 2006
    #6
  7. Chris L.

    Xicheng Guest

    Chris L. wrote:
    > Dear All,
    > I am trying to match a specific pattern using grep.
    >
    > my @results=grep(/$cominput/,@common);
    > print "@results";
    >
    > Naturally,Grep is only printing the lines that variable '$cominput' is
    > found on. My dilemma is I want to print a pattern. Specifically, where
    > variable '$cominput' is found all the way until the character '<' is
    > found. Example,
    >
    > <$cominput 7894596 isnlpop 78304 plmeitn 4457624 knmljebn
    > 93643456346500 lfnsndh 235 hfgnsdljjtngf 7753 fhs 8694039486 jfsndfkgs
    > jsdhfnskdk 753299658 hgnsnd 2573275 nvndjgfi 847523
    > <
    > I would like to grep from "$cominput" to the character "<".
    >
    > I have looked into the map function and several pattern matching
    > examples from google searches, ie:
    > while (<>) {
    > if (/BEGIN PATTERN/ .. /END PATTERN/) {
    > }
    > }

    If you are working on arrays instead of files, you may try map instead
    of grep, coz the later does nothing on your array elements..
    ===========
    use strict; use warnings;
    use Data::Dumper;
    my @array = (
    'sfdsgfdhgdh<$cominput 7894596 isnlpop 78304 plmeitn 4457624
    knmljebn
    93643456346500 lfnsndh 235 hfgnsdljjtngf 7753 fhs 8694039486 jfsndfkgs
    jsdhfnskdk 753299658 hgnsnd 2573275 nvndjgfi 847523 <dsfgdsg ',
    'asdf<< afsef
    asefsdfg <$cominput ',
    'sfdsgfdhgdh<$cominput dfdsg
    111
    222 < < ',
    '
    jsdhfnskdk 753299658 hgnsnd 2573275 nvndjgfi 847523 <dsfgdsg ',
    );
    print Dumper \@array;
    my @tmp = map {/<\$cominput([^<]*)</} @array;
    print Dumper \@tmp;
    ==============
    Best,
    Xicheng

    > But nothing seems to be working. is there a better way to accomplish
    > this??
    > Thank you very much for your time.
    > Chris
     
    Xicheng, Feb 10, 2006
    #7
  8. Chris L.

    Dr.Ruud Guest

    Eric Schwartz schreef:
    > Jim Gibson:


    >> m/<\$cominput(.*)</s

    >
    > m/<\$cominput([^<]*)</s


    m/<\$cominput(.*?)</s

    --
    Affijn, Ruud

    "Gewoon is een tijger."
     
    Dr.Ruud, Feb 10, 2006
    #8
  9. <> wrote:

    > I don't believe you can grep over multiple lines,



    Of course you can.

    grep() filters a list.

    If the elements of that list contain multiple lines, then grep()
    will select on multiple lines.


    -------------------------
    #!/usr/bin/perl
    use warnings;
    use strict;

    my @list = ("line\n1\n", "line\n2\n");
    foreach my $selected ( grep /2/, @list ) {
    print ">>>$selected<<<";
    }
    -------------------------


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Feb 11, 2006
    #9
  10. Chris L. <> wrote:

    > I am trying to match a specific pattern using grep.
    >
    > my @results=grep(/$cominput/,@common);



    What is the value in $cominput?

    We must know what the pattern is if we are to help.

    What are the values in @common?

    We must know what strings the pattern match will be applied
    to if we are to help.


    > print "@results";
    >
    > Naturally,Grep is only printing the lines that variable '$cominput' is
    > found on.



    From the data that you show below '$cominput' is a _string_
    not a variable.


    > My dilemma is I want to print a pattern.



    I doubt that you want to print a pattern.

    I expect that yo want to print the part of a string that
    matches a pattern.


    > Specifically, where
    > variable '$cominput'



    You mean the _string_ '$cominput' (I think).


    > is found all the way until the character '<' is
    > found. Example,



    Then write a pattern that matches all the way until the
    character '<' is found.


    ><$cominput 7894596 isnlpop 78304 plmeitn 4457624 knmljebn
    > 93643456346500 lfnsndh 235 hfgnsdljjtngf 7753 fhs 8694039486 jfsndfkgs
    > jsdhfnskdk 753299658 hgnsnd 2573275 nvndjgfi 847523
    ><



    Is that really what your data looks like?

    I thought you said that grep() was matching something, but grep()
    won't match anything with what I assume your pattern is.

    I must assume what your pattern is because you have not told
    us what your pattern is.


    > I would like to grep from "$cominput" to the character "<".



    You don't need grep() for that.

    You need a pattern match for that:

    print "$1\n" if $string =~ /(\$cominput[^<]*)/;


    Note that the dollar sign is escaped, because I think you
    are talking about a literal dollar sign, rather than one that
    functions as a sigil on a Perl scalar variable.


    > But nothing seems to be working.



    If you show us what you tried (in a form that allow _us_ to try
    it too) then we could help you fix it.

    But you didn't, so we can't.


    > is there a better way to accomplish
    > this??



    A "better way" implies that you have discovered at least one way.

    I get the impression that you do not have _any_ ways of accomplishing "this".


    > Thank you very much for your time.



    Your post is so chock full of inconsistencies that loose (incorrect)
    terminology that I cannot divine what you want, nor what you have
    tried.

    I cannot answer your incomprehensible question.

    Have you seen the Posting Guidelines that are posted here frequently?


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Feb 11, 2006
    #10
  11. Chris L.

    Joe Smith Guest

    Xicheng wrote:

    > If you are working on arrays instead of files, you may try map instead
    > of grep, coz the later does nothing on your array elements..


    No, grep does not change array elements.
    It's s/// that changes array elements, for both grep and map.
    -Joe
     
    Joe Smith, Feb 12, 2006
    #11
  12. Chris L.

    Joe Smith Guest

    Tad McClellan wrote:
    > <> wrote:
    >> I don't believe you can grep over multiple lines,

    >
    > Of course you can.


    We're talking about a pattern that takes multiple lines to match.

    > grep() filters a list.
    >
    > If the elements of that list contain multiple lines, then grep()
    > will select on multiple lines.


    But if the pattern you're searching for is spread over several
    lines, a simple grep won't match. Using the .. range operator
    may return more than is expected.

    Here I'm searching for text that is after 'START' and before 'END',
    stretching over several lines:

    linux% cat test.pl
    $string1 = "zero\n it STARTs here\n middle line\n the END line\n done\n";
    ($match_without_s) = $string1 =~ /START(.*)END/;
    ($match_with_s) = $string1 =~ /START(.*)END/s;
    print "Without s = '$match_without_s'\n";
    print "With s = '$match_with_s'\n";
    @lines = $string1 =~ /(.*\n)/g;
    @match = grep /START(.*)END/, @lines;
    @match_s = grep /START(.*)END/s, @lines;
    @match__ = grep /START(.*)/ .. /(.*)END/, @lines;
    print "Without s = '@match'\n";
    print "With s = '@match_s'\n";
    print "with .. = '@match__'\n";

    linux% perl test.pl
    Without s = ''
    With s = 's here
    middle line
    the '
    Without s = ''
    With s = ''
    with .. = ' it STARTs here
    middle line
    the END line
    '

    -Joe
     
    Joe Smith, Feb 12, 2006
    #12
  13. Chris L.

    Xicheng Guest

    Joe Smith wrote:
    > Xicheng wrote:
    >
    > > If you are working on arrays instead of files, you may try map instead
    > > of grep, coz the later does nothing on your array elements..

    >
    > No, grep does not change array elements.
    > It's s/// that changes array elements, for both grep and map.
    > -Joe


    I guess I didnt make it clear in my original post. here I actually
    meant that the elements in grep's return-list do not have differences
    with the corresponding element in the original array. but map's do...
    that's so-called differences between FILTER and TRANSFER..

    the returned list of grep(FILTER) may have different number of elements
    from the original array, but the corresponding elements keep the SAME
    contents...

    the returned list of map(TRANSFER) may have different contents, but
    generally the number of element are the same except when map-block or
    expressions return *undefined*....

    In OP's post, he can surely use "map" to extract data from his array
    elements which may contain multiple lines..

    For his given multiple-line text-blocks, no need to use (.*) and 's'
    modifier, capturing ([^<]*) does all the tricks for him, either they
    are already in a single string like array elements, or read by
    paragraph-mode, slurp-mode or whatever multiline-modes..

    "A..B" expression is not useful for his case, which extracts data by
    line-mode...

    Xicheng
     
    Xicheng, Feb 12, 2006
    #13
  14. Chris L.

    Anno Siegel Guest

    Xicheng <> wrote in comp.lang.perl.misc:
    > Joe Smith wrote:
    > > Xicheng wrote:
    > >
    > > > If you are working on arrays instead of files, you may try map instead
    > > > of grep, coz the later does nothing on your array elements..

    > >
    > > No, grep does not change array elements.
    > > It's s/// that changes array elements, for both grep and map.
    > > -Joe

    >
    > I guess I didnt make it clear in my original post. here I actually
    > meant that the elements in grep's return-list do not have differences
    > with the corresponding element in the original array. but map's do...
    > that's so-called differences between FILTER and TRANSFER..


    That distinction gets blurry when the test function in a filter has
    the side-effect of changing the list element it's looking at, as
    with s///. In that case, the elements that come out of grep may
    not have been among those that went in.

    > the returned list of grep(FILTER) may have different number of elements
    > from the original array, but the corresponding elements keep the SAME
    > contents...


    Conceptually, yes. Practically, sometimes not.

    > the returned list of map(TRANSFER) may have different contents, but
    > generally the number of element are the same except when map-block or
    > expressions return *undefined*....


    Oh no. Undefined values are registered nicely with map. The block
    has to return nothing (an empty list) if it doesn't want to contribute
    to the result.

    [...]

    > "A..B" expression is not useful for his case, which extracts data by
    > line-mode...


    I'm not sure what that means, but scalar .. can certainly be useful
    with grep.

    Anno
    --
    $_='Just another Perl hacker'; print +( join( '', map { eval $_; $@ }
    'use warnings FATAL => "all"; printf "%-1s", "\n"', 'use strict; a',
    'use warnings FATAL => "all"; "@x"', '1->m') =~
    m|${ s/(.)/($1).*/g; \ $_ }|is),',';
     
    Anno Siegel, Feb 12, 2006
    #14
  15. Chris L.

    Xicheng Guest

    Anno Siegel wrote:
    > Xicheng <> wrote in comp.lang.perl.misc:
    > > Joe Smith wrote:
    > > > Xicheng wrote:
    > > >
    > > > > If you are working on arrays instead of files, you may try map instead
    > > > > of grep, coz the later does nothing on your array elements..
    > > >
    > > > No, grep does not change array elements.
    > > > It's s/// that changes array elements, for both grep and map.
    > > > -Joe

    > >
    > > I guess I didnt make it clear in my original post. here I actually
    > > meant that the elements in grep's return-list do not have differences
    > > with the corresponding element in the original array. but map's do...
    > > that's so-called differences between FILTER and TRANSFER..

    >
    > That distinction gets blurry when the test function in a filter has
    > the side-effect of changing the list element it's looking at, as
    > with s///. In that case, the elements that come out of grep may
    > not have been among those that went in.
    >
    > > the returned list of grep(FILTER) may have different number of elements
    > > from the original array, but the corresponding elements keep the SAME
    > > contents...



    > Conceptually, yes. Practically, sometimes not.


    yeah, if you count some expressions like s///,tr///, the elements in
    the return list may not necessarilly have the same contents as the
    corresponing one in the original array.. I didnt notice that, and I
    actually have never used those expressions in "grep" before. thanks for
    pointing it out to me..:)

    > > the returned list of map(TRANSFER) may have different contents, but
    > > generally the number of element are the same except when map-block or
    > > expressions return *undefined*....

    >
    > Oh no. Undefined values are registered nicely with map. The block
    > has to return nothing (an empty list) if it doesn't want to contribute
    > to the result.


    This may come from my experience, when I use:

    my @tmp = map {/(sth)/} (list);
    print Dumper \@tmp;

    and when the map condition are controlled by regex and parenthesis
    capturings, I noticed that all the elements which donot satisfy the
    condition and thus should register *undefined* in @tmp do not show up
    in the printing list of "print Dumper \@tmp". so I supposed these
    *undefined* elements are automatically filtered out. you may take a
    look at the code I posted in this thread where I did use "map" to
    filter out some array elements in the printing result....:)

    > > "A..B" expression is not useful for his case, which extracts data by
    > > line-mode...

    >
    > I'm not sure what that means, but scalar .. can certainly be useful
    > with grep.


    I didnot mean to use it in "grep", and I actually meant using "A..B" as
    conditional expression to extract data, i.e.

    print $sth if /A/../B/;

    which reads/writes data by line-mode unless he resets $/.

    Best,
    Xicheng

    >
    > Anno
    > --
    > $_='Just another Perl hacker'; print +( join( '', map { eval $_; $@ }
    > 'use warnings FATAL => "all"; printf "%-1s", "\n"', 'use strict; a',
    > 'use warnings FATAL => "all"; "@x"', '1->m') =~
    > m|${ s/(.)/($1).*/g; \ $_ }|is),',';
     
    Xicheng, Feb 12, 2006
    #15
  16. Joe Smith <> wrote:
    > Tad McClellan wrote:
    >> <> wrote:
    >>> I don't believe you can grep over multiple lines,

    >>
    >> Of course you can.

    >
    > We're talking about a pattern that takes multiple lines to match.



    Yes, I gathered that much.


    >> grep() filters a list.
    >>
    >> If the elements of that list contain multiple lines, then grep()
    >> will select on multiple lines.

    >
    > But if the pattern you're searching for is spread over several
    > lines, a simple grep won't match.



    Sure it will, if the _list elements_ are spread over several
    lines and otherwise match the pattern.

    -------------------
    #!/usr/bin/perl
    use warnings;
    use strict;

    my @list = ("line\n1\n", "line\n2\n");
    foreach my $selected ( grep /e\n2/, @list ) {
    print ">>>$selected<<<";
    }
    -------------------


    > ($match_with_s) = $string1 =~ /START(.*)END/s;



    Whether the pattern needs an m//s modifier or not is independant
    of whether grep can "filter over multiple lines".

    (and you probably want non-greedy matching there.)


    > @lines = $string1 =~ /(.*\n)/g;
    > @match = grep /START(.*)END/, @lines;
    > @match_s = grep /START(.*)END/s, @lines;
    > @match__ = grep /START(.*)/ .. /(.*)END/, @lines;



    But now the elements of the list do not contain multiple lines,
    as in the predicate I gave in my followup.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Feb 13, 2006
    #16
  17. Chris L.

    Anno Siegel Guest

    Xicheng <> wrote in comp.lang.perl.misc:
    > Anno Siegel wrote:
    > > Xicheng <> wrote in comp.lang.perl.misc:
    > > > Joe Smith wrote:
    > > > > Xicheng wrote:


    > > > the returned list of map(TRANSFER) may have different contents, but
    > > > generally the number of element are the same except when map-block or
    > > > expressions return *undefined*....

    > >
    > > Oh no. Undefined values are registered nicely with map. The block
    > > has to return nothing (an empty list) if it doesn't want to contribute
    > > to the result.

    >
    > This may come from my experience, when I use:
    >
    > my @tmp = map {/(sth)/} (list);
    > print Dumper \@tmp;
    >
    > and when the map condition are controlled by regex and parenthesis
    > capturings, I noticed that all the elements which donot satisfy the
    > condition and thus should register *undefined* in @tmp do not show up
    > in the printing list of "print Dumper \@tmp". so I supposed these
    > *undefined* elements are automatically filtered out. you may take a
    > look at the code I posted in this thread where I did use "map" to
    > filter out some array elements in the printing result....:)


    Well, a regex that doesn't capture anything doesn't return undef, it
    returns nothing. The difference is subtle and not always noticeable.
    If you assign from a non-match

    my ( $x) = 'abc' =~ /(X)/;

    $x will become undefined, so it looks like that is what the regex returned.
    However, when you write

    my @x = 'abc' =~ /(X)/;

    you'll notice that the list is empty. Similarly, in scalar context

    my $x = ();

    and

    my $x = ( undef);

    are indistinguishable by their result, though fundamentally different.
    In list context the difference becomes apparent:

    my @x = ();
    my @x = ( undef);

    Anno
    --
    $_='Just another Perl hacker'; print +( join( '', map { eval $_; $@ }
    'use warnings FATAL => "all"; printf "%-1s", "\n"', 'use strict; a',
    'use warnings FATAL => "all"; "@x"', '1->m') =~
    m|${ s/(.)/($1).*/g; \ $_ }|is),',';
     
    Anno Siegel, Feb 13, 2006
    #17
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Blake

    Multiple File Grep

    Blake, Jul 27, 2004, in forum: Perl Misc
    Replies:
    3
    Views:
    124
    Greg Bacon
    Jul 27, 2004
  2. Buck Turgidson

    Grep Text File for Lines Containing 1 or 2 Words

    Buck Turgidson, Jan 25, 2005, in forum: Perl Misc
    Replies:
    6
    Views:
    129
    John W. Krahn
    Jan 26, 2005
  3. PerlFAQ Server
    Replies:
    0
    Views:
    175
    PerlFAQ Server
    Jan 14, 2011
  4. PerlFAQ Server
    Replies:
    0
    Views:
    160
    PerlFAQ Server
    Apr 19, 2011
  5. Cah Sableng
    Replies:
    0
    Views:
    247
    Cah Sableng
    Apr 23, 2007
Loading...

Share This Page