• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 597
  • Last Modified:

Perl RegEx Question

Hi,

I have some data in a string which looks something like this:

>gavin1
score = 10, evalue = 1000000
length = 50, width = 100
Alignment = plus / minus
>gavin2
score = 20, evalue = 2000000
length = 100, width = 200
Alignment = plus / minus
>gavin 3
score = 60, evalue = 300000
length = 2, width = 50
Alignment = plus / plus

Basically I want to be able to quickly pull out just the last record (the one that ends plus / plus).
Is there any way I can get a regex to read from the end of the string and not the beginning?

As it stands, if I try a regex like (/>.*?plus\s\/\splus/s)  it pulls out all 3 entries (since it starts reading from the beginning of the string and expands outwards).  Any tips on how I can do this without splitting into arrays etc....?

Cheers in advance,

tb34
0
travisbickle34
Asked:
travisbickle34
  • 3
  • 2
  • 2
2 Solutions
 
geotigerCommented:
Here it is :

#!/usr/local/bin/perl
#
my $input = <<EoS;
>gavin1
score = 10, evalue = 1000000
length = 50, width = 100
Alignment = plus / minus
>gavin2
score = 20, evalue = 2000000
length = 100, width = 200
Alignment = plus / minus
>gavin 3
score = 60, evalue = 300000
length = 2, width = 50
Alignment = plus / plus
EoS

my $re = qr/>[^>]*plus\s*\/\s*plus\s*/si;
# print $input;
print "RE = $re\n";

local $\;
my @a = ($input =~ /$re/sg);

for my $i (0..$#a) {
   print $a[$i];
}

> ./tst87pat.pl
RE = (?si-xm:>[^>]*plus\s*/\s*plus\s*)
>gavin 3
score = 60, evalue = 300000
length = 2, width = 50
Alignment = plus / plus
0
 
inq123Commented:
Just one line of code suffice (not counting the lines in your input string):

my $input = <<"END";
>gavin1
score = 10, evalue = 1000000
length = 50, width = 100
Alignment = plus / minus
>gavin2
score = 20, evalue = 2000000
length = 100, width = 200
Alignment = plus / minus
>gavin 3
score = 60, evalue = 300000
length = 2, width = 50
Alignment = plus / plus
END

print "this is the record you need:\n$1\n" if($input =~ /(>[^>]+plus\s\/\splus)/);

if you know this is always the last record, then /(>[^>]+)$/ would do.
0
 
travisbickle34Author Commented:
Cheers ing123 - That works perfectly.

Any chance of a brief explanation of how that regex works?  I would like to know for the future!

tb34
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
geotigerCommented:

Did I get the regular expression correct? I think it deserve some credits!

The other lines are just for inputing and displaying information.
0
 
travisbickle34Author Commented:
To be honest I only tested the more concise version.

Apologies - perhaps a moderator can do a points split or something?

tb34
0
 
travisbickle34Author Commented:
Done.

Cheers guys.

tb34
0
 
inq123Commented:
OK, some explanation (I assume you know the very basics):

/(>[^>]+plus\s\/\splus)/
[^>] means any character that is not '>'
This regex works because it gets any section that ends with plus / plus.  One might tinker with the \s in the regex to add \s* just in case you want to capture plus/plus and plus     /      plus.

/(>[^>]+)$/
$ at end of regex means match end of string.  This one works because it always gets the last section (not necessarily plus / plus).

One more comment, which I agree that geotiger's regex works, I don't think his answer is a good answer (no offense, just purely from a technical aspect).  Now here's why:

my $re = qr/>[^>]*plus\s*\/\s*plus\s*/si;

1. qr// is unnecessary because it only matters when you interpolate variables.
2. /s is not necessary either since [^>] includes \n, which is proven in my working solutions.

Then in $input =~ /$re/sg, there's /s again, and it's unecessary again.

The good thing about his answer is that it uses /g to capature all 'plus / plus' sections, but it does not seem to be necessary (and even incorrect) since you specified that you just wanted the last plus / plus section in your question, not all of them or first of them or ...
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 3
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now