Connecting Tech Pros Worldwide Forums | Help | Site Map

switching from bash to Perl

Newbie
 
Join Date: Nov 2006
Posts: 25
#1: Nov 10 '06
Hi,
I recently started using bash and wrote some code to find certain IPs and related stuff in the leases files by using grep
I am trying to switch to perl. I am a bigginer and trying to learn perl by reading stuff on net.
I am getting stuck at following point
I wrote in bash
grep $IP data061009 -A 6

Now in perl I am writing
@result= grep (/$IP/, $_) in a while loop.
How do I incorporate '-A 6' part in perl
Please help.

miller's Avatar
Moderator
 
Join Date: Oct 2006
Location: San Francisco, CA
Posts: 830
#2: Nov 10 '06

re: switching from bash to Perl


There is no perl equivalent functionality for grep by default. But you can add it programmatically. Per the grep --help documentation.

Expand|Select|Wrap|Line Numbers
  1.   -A, --after-context=NUM   print NUM lines of trailing context
  2.  

Here is the code you want scetched out:

Expand|Select|Wrap|Line Numbers
  1. my $infile = "data061009";
  2. open(IN, "$infile") or die "open $inFile: $!";
  3. my $A = 0; # Variable to keep track of last seen.
  4. my @results = grep {/$IP/ ? $A=6 : $A-- > 0} <IN>;
  5. close(IN) or die "close $inFile: $!";
  6.  
You could also do the same thing using a for loop to make it more readable. But that gives you exactly what you want.
Newbie
 
Join Date: Nov 2006
Posts: 25
#3: Nov 13 '06

re: switching from bash to Perl


Hi, thanks a lot!! It really worked!! But they I have another basic question, how did it work? I mean I am trying to understand the code you sent...but with my limited knowledge of Perl ...I am not able to understand what exactly is happening there!!
I am also reading a book on Perl side by side....but honestly ....there is so much in it...and I dont know where to look for my difficulties and so on.
Is there any quick/ smart way to learn perl?
Thanks again!!
miller's Avatar
Moderator
 
Join Date: Oct 2006
Location: San Francisco, CA
Posts: 830
#4: Nov 13 '06

re: switching from bash to Perl


I'm glad my code example worked, but I'm not going to teach you perl. That's not what the forums are for, and really wouldn't be a good use of either of our times. Here is the code that I posted to you in a more verbose form to make it more readable. The nice and bad thing about perl is that it truly gives you the ability to do things in many different ways. Some of them very compact, but definitely harder to understand for the beginner.

Expand|Select|Wrap|Line Numbers
  1. my $infile = "data061009";
  2. open(IN, "$infile") or die "open $inFile: $!";
  3.  
  4. # Dumbing Down these two lines of code:
  5. #my $A = 0; # Variable to keep track of last seen.
  6. #my @results = grep {/$IP/ ? $A=6 : $A-- > 0} <IN>;
  7.  
  8. my @results = (); # Accumulate content.
  9. my $trailing = 0;
  10.  
  11. while (my $line = <IN>) {
  12.     if ($line =~ /$IP/) {
  13.         # Match Found: Save Results, and queue for 5 more lines to save
  14.         push @results, $line;
  15.         $trailing = 5;
  16.     } elsif ($trailing > 0) {
  17.         # Trailing Content: Save Results, decrement counter by 1.
  18.         push @results, $line;
  19.         $trailing--;
  20.     }
  21. }
  22. # END Dumb Down
  23.  
  24. close(IN) or die "close $inFile: $!";
  25.  
This code should explain what is occuring logically. If you want to learn more about grep, regular expressions, the $_ variable, the ?: operator, and such, you'll just have to do more reading and scrounging for code examples. Also, a little time just playing around with code snippets always helps to learn what things do. But I learned perl the hard way, so I really don't know what else to suggest that would make the process easier for someone else.
Newbie
 
Join Date: Nov 2006
Posts: 25
#5: Nov 14 '06

re: switching from bash to Perl


Thanks...!
Newbie
 
Join Date: Nov 2006
Posts: 25
#6: Nov 15 '06

re: switching from bash to Perl


In bash I could access a part of a string by using [ : : ]
For example:
$string=bookshop;
new_string=${string:0:4)
echo $new_string

The code above would retrun
book

Is there any way I can do similar thing in Perl?
Please help.

Miller,
I have understood the ?: operator from our previous discussion. Please let me know if I am right,
1. if grep is successful, A is set to 6 , print the current line
2. if grep is not successful, decremet A , print the current line

This would print 6 lines after the line with the grep argument,
If the grep is not successful right in the start, A =1 and decrementing it would push it to 0, >0 condition not satisfied, so dont print current line.

Is that the right interpretation of the code?
miller's Avatar
Moderator
 
Join Date: Oct 2006
Location: San Francisco, CA
Posts: 830
#7: Nov 16 '06

re: switching from bash to Perl


Quote:

Originally Posted by Studentmadhura05

Is there any way I can access a part of a string in Perl?

Look at: http://perldoc.perl.org/functions/substr.html

Quote:

Originally Posted by miller

my $A = 0;
my @results = grep {/$IP/ ? $A=6 : $A-- > 0} <IN>;

Quote:

Originally Posted by Studentmadhura05

I have understood the ?: operator from our previous discussion. Please let me know if I am right,
1. if grep is successful, A is set to 6 , print the current line
2. if grep is not successful, decremet A , print the current line

This would print 6 lines after the line with the grep argument,
If the grep is not successful right in the start, A =1 and decrementing it would push it to 0, >0 condition not satisfied, so dont print current line.

Is that the right interpretation of the code?

Close, but not quite verbally correct:

1. if the pattern /$IP/ matches, then $A=6 is used as the condition for grep. The statement $A=6 sets $A to 6, and then returns true (6), so the line is added to @results.
2. if the pattern /$IP/ doesn't match, then $A-- > 0 is used as the condition for grep. The statement $A-- > 0 is treated as $A > 0 by grep, and then a decrement is done to $A after the value check. So if the pre decrement value of $A is greater than 0, that the line is also added to @results.

Again, it is a lot harder to write out what is happening in words, than it is to just write it out in perl. But thank you for trying. It sounds like you have a good grasp of what was going on there. The hardest part to understand being the operator precedence.

Warning more advanced, probably unneeded knowledge to follow

Your use of /$IP/ is probably not completely correct. I'm assuming that $IP is an ip address. So if $IP='192.168.1.1', the pattern would be /192.168.1.1/. You might notice there is a problem with the above regular expression, namely the dots (.). That catches a lot more ip address than you probably intend, like 192.168.141.255. Instead, you want the dots to be treated as literals, and there is an easy shortcut for you to do this.

Just use /\Q$IP\E/ as your pattern.

Try printing out "\Q$IP\E" to see what those escape sequences actually do. They come in handle in regular expression all the time when working with literals. You can read more about them at:

http://perldoc.perl.org/functions/quotemeta.html
http://perldoc.perl.org/perlretut.ht...racter-classes
Newbie
 
Join Date: Nov 2006
Posts: 25
#8: Nov 16 '06

re: switching from bash to Perl


Thanks Miller! I am kind of getting a little hang of coding in perl. I hope I improve....
I managed to use the 'substr' and it worked.
I am trying now to do the coding to get functionality equivalant to '-B' option of grep in perl. I will get back to you if I get stuck again.:-)
Thanks a lot for pointing out the posiible problems of using just /$IP/ as pattern!!!
Thanks!
miller's Avatar
Moderator
 
Join Date: Oct 2006
Location: San Francisco, CA
Posts: 830
#9: Nov 16 '06

re: switching from bash to Perl


Quote:

Originally Posted by Studentmadhura05

I am trying now to do the coding to get functionality equivalant to '-B' option of grep in perl. I will get back to you if I get stuck again.:-)

Expand|Select|Wrap|Line Numbers
  1. grep --help
  2.   -B, --before-context=NUM  print NUM lines of leading context
  3.  
That's a very good challenge. It's pretty straight forward to do that, but it won't be nearly as clean algorithmically. Good luck.
Newbie
 
Join Date: Nov 2006
Posts: 25
#10: Nov 16 '06

re: switching from bash to Perl


I got it!!!
I do not know how to copy paste the code from putty...so I am typing it out again here...so there might be minor typing errors...but the code worked!!
Here it is:

while (<IN>) {
push @previous3, $_;
shift @previous3 if @previous3 > 3;
@host= grep (/$hardware/, $_);
my $host = @host;

if ($host == 1) {
print @previous3;
}


What do you think?
miller's Avatar
Moderator
 
Join Date: Oct 2006
Location: San Francisco, CA
Posts: 830
#11: Nov 16 '06

re: switching from bash to Perl


Quote:

Originally Posted by Studentmadhura05

I got it!!!
I do not know how to copy paste the code from putty...so I am typing it out again here...so there might be minor typing errors...but the code worked!!
Here it is:

while (<IN>) {
push @previous3, $_;
shift @previous3 if @previous3 > 3;
@host= grep (/$hardware/, $_);
my $host = @host;

if ($host == 1) {
print @previous3;
}

What do you think?

Nice job.

Cleaning up your code to remove the needless use of grep first:

Expand|Select|Wrap|Line Numbers
  1. while (<IN>) {
  2.     push @previous3, $_;
  3.     shift @previous3 if @previous3 > 3;
  4.  
  5.     if (/$hardware/) {
  6.         print @previous3;
  7.     }
  8. }
  9.  
Now you have one flaw in your logic though. What happens if two lines in a row that match /$hardware/?
Newbie
 
Join Date: Nov 2006
Posts: 25
#12: Nov 16 '06

re: switching from bash to Perl


I know what you are saying. But since I know the structure of the input files I am scanning ...this problem wont come in my work. But I agree...the code is not foolproof. !
miller's Avatar
Moderator
 
Join Date: Oct 2006
Location: San Francisco, CA
Posts: 830
#13: Nov 16 '06

re: switching from bash to Perl


Quote:

Originally Posted by Studentmadhura05

I know what you are saying. But since I know the structure of the input files I am scanning ...this problem wont come in my work. But I agree...the code is not foolproof. !

Fine, if you won't fix it. I will.

Expand|Select|Wrap|Line Numbers
  1. while (<IN>) {
  2.     push @previous3, $_;
  3.     shift @previous3 if @previous3 > 3;
  4.  
  5.     if (/$hardware/) {
  6.         print @previous3;
  7.         @previous3 = (); # <--- Fool proof now :)
  8.     }
  9. }
  10.  
QED.
Newbie
 
Join Date: Nov 2006
Posts: 25
#14: Nov 16 '06

re: switching from bash to Perl


Cool!!
I will bug you in coming days if again get stuck.:)
Reply