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

Suppose u have a file

860414 31 290 28 299 00931.17 HIGH CL1122

860412 501 541 501 554 00977.18 LRR_4 CL0022

860415 501 541 511 564 00977.33 LOW CL0023

Desired output If a particular column contain desired "HIGH", "LRR", "LOW" in one file print 1. Otherwise print 0.

So you will have lot of files where either of one or two not all three are present then print 0 so on..

#!/usr/bin/perl -w open (FILE,"$ARGV[0]") or die; my @temp =<FILE>; close FILE; my $f=join("",@temp); my @lastreco=split("\n",$f); foreach (@lastreco) { my @t= split("\t",$_); if ($t[7] =~ /HIGH/ && /LOW/ && /LRR/) { print "$1\n"; } }

Replies are listed 'Best First'.
Re: print to match multiple pattern
by ww (Archbishop) on Sep 10, 2012 at 12:57 UTC
    "Suppose u " read the instrxns around the text entry box: use <code>...</code> tags around code and data.

    Since you didn't use code tags around the data, those who try to check your code are at a disadvantage... which is a bad approach when asking for free help.

    Then you assure us that the error messages are the "desired output."

    So, obviously, problem solved. Moving on...

    But maybe that's another mistake... so you get advice from Corion and RichardK to check the content of @t and, specifically, $t[7] which, thus far, you don't appear to have done since you tell us the "data in the 8th column that shows "HIGH", "LOW", "LRR" " but which we can't verify/troubleshooot based on anything you've shown... but which is NOT the case in your sample data, where those strings occur in the seventh column, and should be found in $t[6] if the only problem with your sample data is your formatting and html's rendering of the separators as single spaces.

    #!/usr/bin/perl -w use 5.014; #992723 my @temp =<DATA>; my $f=join("",@temp); my @lastreco=split("\n",$f); foreach (@lastreco) { my @t= split("\t",$_); say "testing: $t[6]"; if ($t[6] =~ /HIGH/ && /LOW/ && /LRR/) { print "matched: $1\n"; } } =head unmodified sample data has spaces, not tabs 860414 31 290 28 299 00931.17 HIGH CL1122 860412 501 541 501 554 00977.18 LRR_4 CL0022 860415 501 541 511 564 00977.33 LOW CL0023 =cut __DATA__ 860414 31 290 28 299 00931.17 HIGH CL1122 654321 404 403 402 401 011.1111 ARR34 CL0024 860412 501 541 501 554 00977.18 LRR_4 CL0022 860415 501 541 511 564 00977.33 LOW CL0023 123456 404 403 402 401 011.1111 MED CL0024

    Output:

    testing: HIGH testing: ARR34 testing: LRR_4 testing: LOW testing: MED

    And no, this doesn't address why, even with the corrections above, you're not getting a match... but that answer will be found on numerous (that is, "many," but not "all") nodes here using the term "alternation" or in the documentation for logical operators.

Re: print to match multiple pattern
by aitap (Curate) on Sep 10, 2012 at 12:43 UTC

    Don't read the whole file into memory. Read it line by line instead:

    while (<FILE>) { ... # $_ is the current line }
    (see Range operators).

    Also, there is no need in the @t array: just slice the array returned by split:

    if ((split "\t",$_)[7] =~ /^(?:HIGH|LOW|LRR)$/)

    Also, your condition ($t[7] =~ /HIGH/ && /LOW/ && /LRR/) will never be true as long as one line never contains "HIGH", "LOW" and "LRR" at the same time.

    Sorry if my advice was wrong.
Re: print to match multiple pattern
by Kenosis (Priest) on Sep 10, 2012 at 14:53 UTC

    If the words "HIGH", "LRR" and "LOW" can only appear in the column you're interested in (looks like it, given your data set), then try the following on the string that contains your file's entire contents:

    use Modern::Perl; my $data = <<END; 860414 31 290 28 299 00931.17 HIGH CL1122 860412 501 541 501 554 00977.18 MED CL0022 860412 501 541 501 554 00977.18 LRR_4 CL0022 860412 501 541 501 554 00977.18 SSA CL0022 860415 501 541 511 564 00977.33 LOW CL0023 END say $data =~ /(?=.*HIGH)(?=.*LRR)(?=.*LOW)/s ? 1 : 0;

    Output:

    1

    The regex effectively 'ANDs' the terms together.

Re: print to match multiple pattern
by frozenwithjoy (Priest) on Sep 10, 2012 at 21:23 UTC
    I see three problems right off:

    First, the snippet of the file that you show is space-delimited, but you are splitting each line on the tabs.

    Second, when counting elements in an array in Perl, you should start at zero, not one. HIGH/LRR/LOW is in the 7th column which would be element number 6 (or $t[6]) if the line is properly split.

    Third, I don't think you mean to test that column 7 matches ALL of the keywords at once.

Re: print to match multiple pattern
by prashantktyagi (Scribe) on Sep 10, 2012 at 11:35 UTC
    You forgot to mention the issue.. :P
      Desired output comes as ..

      Use of uninitialized value $t7 in pattern match (m//) at ./program_2.pl line 14.

      Use of uninitialized value $t7 in pattern match (m//) at ./program_2.pl line 14.

      Use of uninitialized value $t7 in pattern match (m//) at ./program_2.pl line 14.

        So, have you looked at the contents of @t? Have you verified that it contains what you want? Perl starts counting array indices at 0. Are you sure that the data in the eighth column is what you want?