简体   繁体   中英

Get after last occurrence in string using regular expressions

I have a SQL string and I need to get the table name from the main 'FROM' value. I need to find the last 'FROM' occurrence which may or may not have additional constraints following it. Here are a few ways the string could look:

$input = "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account WHERE title = 'president'";
$input = "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account LIMIT 1";
$input = "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account OFFSET 3";
$input = "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account ANYTHING_HERE_REALLY";
$input = "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account";

Expected output for all is: Account

From scouring the forum any playing around, this is the direction I'm going, but I know it's not correct.

preg_match('/.*FROM\s([^]]+)\sWHERE/', $input, $output);

First of all, it is bad practice to use regular expressions for cascading content like (cascading) queries. But here we go...

Simply match the sequence of non-spaces after the FROM .

Note: because of the greedyness of the Kleene star of the .* , it will definitely look for the latest match. You're pattern actually aims to overspecify the problem by expecting a WHERE clause.

preg_match('/.*FROM\s+(\S+)/', $input, $output);

Example (with the given examples and interactive php -a ):

$ php -a
php > $input = "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account WHERE title = 'president'";
php > preg_match('/.*FROM\s+(\S+)/', $input, $output);var_dump($output);
array(2) {
  [0]=>
  string(80) "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account"
  [1]=>
  string(7) "Account"
}
php > $input = "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account LIMIT 1";
php > preg_match('/.*FROM\s+(\S+)/', $input, $output);var_dump($output);
array(2) {
  [0]=>
  string(80) "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account"
  [1]=>
  string(7) "Account"
}
php > $input = "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account OFFSET 3";
php > preg_match('/.*FROM\s+(\S+)/', $input, $output);var_dump($output);
array(2) {
  [0]=>
  string(80) "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account"
  [1]=>
  string(7) "Account"
}
php > $input = "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account ANYTHING_HERE_REALLY";
php > preg_match('/.*FROM\s+(\S+)/', $input, $output);var_dump($output);
array(2) {
  [0]=>
  string(80) "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account"
  [1]=>
  string(7) "Account"
}
php > $input = "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account";
php > preg_match('/.*FROM\s+(\S+)/', $input, $output);var_dump($output);
array(2) {
  [0]=>
  string(80) "SELECT title, (SELECT name FROM Contact WHERE name = 'foo') as name FROM Account"
  [1]=>
  string(7) "Account"
}

This should work for you:

preg_match_all('/FROM\s?(\S+)/', $input, $output);

$output:

Array
(
    [0] => Array
        (
            [0] => FROM Contact
            [1] => FROM Account
        )

    [1] => Array
        (
            [0] => Contact
            [1] => Account
        )

)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM