Regex OR Operator

B

Buck

I am fairly new to regexes. I have the following to parse a SQL
statement, looking for either "FROM" or "JOIN". Is there a way to
shorten the following, so I don't have to repeat the regex after the
word "FROM" or "JOIN"?

from \w*\W+as\W+\w*|join \w*\W+as\W+\w*

e.g., I want it to look like this, but it doesn't work:

[from\join] \w*\W+as\W+\w*
 
G

Greg Bacon

: I am fairly new to regexes. I have the following to parse a SQL
: statement, looking for either "FROM" or "JOIN". Is there a way to
: shorten the following, so I don't have to repeat the regex after the
: word "FROM" or "JOIN"?
:
: from \w*\W+as\W+\w*|join \w*\W+as\W+\w*
:
: e.g., I want it to look like this, but it doesn't work:
:
: [from\join] \w*\W+as\W+\w*

You're close. Square brackets are for character classes. Your pattern
says match a single character that is one of 'f', 'r', 'o', etc.
followed by a space, and so on.

Use parentheses to group and | for alternatives:

$ cat try
#! /usr/bin/perl

use warnings;
use strict;

my @fragments = (
"from foo as f",
"join bar as b",
);

for (@fragments) {
print "$_: ";

if (/(from|join)\s+\w+\s+as\s+\w+/) {
print "match\n";
}
else {
print "no match\n";
}
}

$ ./try
from foo as f: match
join bar as b: match

This sort of pattern will look much nicer in Perl 6. Fingers crossed.

Hope this helps,
Greg
 
P

Paul Lalli

: I am fairly new to regexes. I have the following to parse a SQL
: statement, looking for either "FROM" or "JOIN". Is there a way to
: shorten the following, so I don't have to repeat the regex after the
: word "FROM" or "JOIN"?
:
: from \w*\W+as\W+\w*|join \w*\W+as\W+\w*
:
: e.g., I want it to look like this, but it doesn't work:
:
: [from\join] \w*\W+as\W+\w*

You're close. Square brackets are for character classes. Your
pattern says match a single character that is one
of 'f', 'r', 'o', etc. followed by a space, and so on.

Use parentheses to group and | for alternatives:
if (/(from|join)\s+\w+\s+as\s+\w+/) {

It should be pointed out that this version of using parentheses has a
side effect. It will cause whatever is matched by the pattern in
parentheses to be saved off in the variable $1. If you do not want
that behavior, you can use non-capturing parentheses. To do so, put
the characters ?: at the start of your subpattern, like so:
if (/(?:from|join}\s+\w+\s+as\s+\w+/) {

These parenthese have the same "clustering" effect, without the side
effect of capturing. You can read more about them in:
perldoc perlretut
perldoc perlre
perldoc perlreref

Paul Lalli
 
P

Paul Lalli

I am fairly new to regexes. I have the following to parse a SQL
statement, looking for either "FROM" or "JOIN". Is there a way
to shorten the following, so I don't have to repeat the regex
after the word "FROM" or "JOIN"?

from \w*\W+as\W+\w*|join \w*\W+as\W+\w*

Greg has already given you the answer to the question you asked. I
would like, however, to give you the answer to the question you,
perhaps, should have asked. That being "How can I parse an SQL
statement to find all the tables that are being selected from?"

The answer to that question is: "Use SQL::Statement". To demonstrate:

$ perl -MSQL::Statement -le'
my $sql = q{SELECT a, b, c FROM alpha JOIN beta WHERE gamma = 0};
my $parser = SQL::parser->new();
my $stmt = SQL::Statement->new($sql, $parser);
my @tables = map { $_->{name} } $stmt->tables();
print "Tables: @tables";
'
Tables: ALPHA BETA

If this is not your true intent, then forgive my assumptions...

Paul Lalli
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,667
Latest member
DaniloB294

Latest Threads

Top