http://www.perlmonks.org?node_id=1028214


in reply to Using grep to pick out Specific lines in a text file

Reformatting your code shows a number of things:

foreach $_ (@array) { @array2 = grep {$_ =~ "unknown type(0x134e) 30.6511 (V6.5.1 FP1)"} ( +@array); print FILE "@array2"; close(FILE);

Could you add a couple of lines of your files, matching and non-matching, that the question becomes easier to understand?

Replies are listed 'Best First'.
Re^2: Using grep to pick out Specific lines in a text file
by itguy87 (Novice) on Apr 11, 2013 at 19:30 UTC

    here is the full code

    use strict; use warnings; my $RootDir = "C:\\Perl"; my $AppDir = "$RootDir\\ibmscripts\\stlogsearch"; my $EtcDir = "$AppDir\\etc\\"; my $sendmail = "C:\\usr\\lib\\sendmail"; my $emailconf = $EtcDir . "email_justme.cfg"; my $outfile = "output.txt"; #my $finallist = "output.txt"; open(FILE, "<data/04102013_loginlogs.txt"); my @array = <FILE>; close(FILE); open(FILE, ">>output.txt"); my @array2 = <FILE>; print "Extracting\n"; foreach $_ (@array) { @array2 = grep {$_ =~ "(0x1346)"} (@array); print FILE "@array2"; close(FILE); system("copy $emailconf $outfile"); open(FILE,">>$outfile"); print FILE "@array2"; close(FILE); system("$sendmail -t < output.txt"); exit;}

      Have you actually walked through the logic of when files are being opened and closed?

      It doesn't make any sense to me to open a file for append mode on line 16, try to read from that file on line 17, print to it on line 21, close it on line 22, open it again on line 25, print to it on line 27, close it on line 29, and then try to print to a closed filehandle on the next iteration of the loop on line 21 again. I think once you sort that out you'll be better off.

      For the sort of thing you're trying to do, slurping into an array and running grep on it repeatedly in a loop isn't really "how it's done". Your situation may be a little more complicated than this, but here's the general algorithm:

      • Open your input and output files.
      • Using a while loop, read from input file: while( <FILE> ) {....
      • Inside the while loop filter for lines of interest (one at a time).
      • Inside the while loop, process the lines of interest (one at a time); in your case, write them to an output/append file.
      • Close the while loop's scope.
      • Close your output and input files.

      Also, place use autodie; toward the top of your script, near the use strict;, so that you can get some basic sanity checking on your file operations.


      Dave

      ...and here now with reading from and writing to file. I leave the system commands out as I do not know what they are intended for.

      use strict; my @patterns = ( 'unknown type\(0x134e\)', '30.6511', '\(V6.5.1 FP1\)' + ); # now read from file instead open FILE, "<", "data/04102013_loginlogs.txt" or die "Cannot open inpu +t file.\n"; my @array = <FILE>; close(FILE); # open output file for writing open OUT, ">>", "output.txt" or die "Cannot open output file.\n"; foreach my $line (@array) { print OUT $line if scalar grep { $line =~ /$_/ } @patterns; } close OUT;

      UPDATE: Removed a ) on line 5.

        Perfect, that worked great. Now that it is working i found another issue. In this where "singer" is i pulled 23 different occurances, i only need to print singer in my out put. That tells me that it does show up in the data log. And Singer does change to multiple values.

        Works great but now i think i want it to look different... woulld look like the blow

        30.6511 (V6.5.1 FP1) KALLATOM@de.ibm.com 255.255.255.255 (then a count of how may timesit showed up)

        well i tried what you have above and it tells me there is a syntax error at line 5

        Ok so this did search this time, My issue is that i need to pull the line that has all of the following true. unknown type(0x134e) 30.6511 (V6.5.1 FP1)

        Here is a line from the data file

        01 XXXXXXXX 10/Apr/13 01:13:10 unknown type(0x134e) 30.6511 (V6.5.1 FP1) Singer 192.168.1.1

      As a first building block, here is a piece of code that reads from the __DATA__ segment and prints a line if one of the patterns fit. Please confirm if this is what you wanted. Some characters in the patterns need to be escaped with backslashes to make it work.

      use strict; my @patterns = ( 'unknown type\(0x134e\)', '30.6511', '\(V6.5.1 FP1\)' + ); my @array = <DATA>; foreach my $line (@array) { print $line if scalar grep { $line =~ /$_/ } @patterns; } __DATA__ no fit unknown type(0x134e) bla bla bla 30.6511 kkkkkkkkkk (V6.5.1 FP1) lllkjlkj 30.6511 klljklljk jkljkljkl