John W. Krahn am Sonntag, 14. Mai 2006 00.11: > Richard Bagshaw wrote: > > I'm very new to perl and I have been trying to solve a problem for a few > > days now, I am reading a file that I use to setup my firewall rules on a > > Linux box, the file contains many lines, but as an example I will show > > just two here :- > > > > iptables -A INPUT -p tcp -s 123.45.678.90 --dport 22 -j ACCEPT > > > > and ... > > > > iptables -A INPUT -p tcp --dport 25 -j ACCEPT > > > > As you can see, the main difference is that line one has the "source ip" > > listed, where as line 2 doesn't. I am writing a regex to basically pull > > all of the pertinent parts from the lines. The below expression works > > perfectly for the first line, but for the 2nd line it does not work. I > > know "why" it doesn't work, but cannot find the correct syntax for > > alternation to make the 2nd line work. > > > > if (/(INPUT) -p (...) -s ([0-9\.]*) --dport ([0-9]+) -j ([A-Za-z].*)/gi) > > { ... code here ... > > } > > > > $1 = INPUT > > $2 = UDP or TCP > > $3 = <IP of SOURCE> > > $4 = <PORT> > > $5 = ACCEPT or REJECT or DROP > > > > Any help would be appreciated. > > If $1 is always 'INPUT' then why capture it?
> Case is usually important or do -s and -S do the same thing? oops, I missed this point (besides others) in my answer. > If you want parsing similar to a shell > then all you need to do is parse on whitespace: > > if ( /INPUT -p (\S+) (?:-s (\S+))? --dport (\S+) -j (\S+)/ ) { > > > If you are trying to use a regular expression to verify that the data is > correct then something like this _may_ work: It does when replacing the \s* with \s+ - at least my iptables complains if arguments are not separated with a space (tested with -p and -s). > if ( /INPUT > \s* > -p \s* (udp|tcp) > \s* > (?: -s \s* ( (?: 0?\d?\d | 1\d\d | 2 (?: [0-4]\d | 5[0-5] ) ) > (?: \. (?: 0?\d?\d | 1\d\d | 2 (?: [0-4]\d | 5[0-5] ) ) ){3} ) > )? \s* > --dport \s* (\d{1,5}) > \s* > -j \s* ([A-Za-z]\S*) > /x ) { > > Or you could "cheat" and let Getopt::Long parse it for you: > > $ perl -MGetopt::Long -MData::Dumper -e' > $_ = q[iptables -A INPUT -p tcp -s 123.45.678.90 --dport 22 -j ACCEPT]; > my %h; > { local @ARGV = split; > GetOptions( \%h, "A=s", "p=s", "s=s", "dport=i", "j=s" ); > } > print Dumper \%h; > ' > $VAR1 = { > 'A' => 'INPUT', > 'p' => 'tcp', > 's' => '123.45.678.90', > 'j' => 'ACCEPT', > 'dport' => 22 > }; The disadvantage may be that it accepts wrong syntax like -ptcp (see remark above), but the idea is great! Dani -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] <http://learn.perl.org/> <http://learn.perl.org/first-response>