Using regular expression subpattern to instead of

2019-09-01 00:58发布

I'm interested if its possible to make include subpattern (child pattern) into a another pattern that would allow me to convert those 2 preg_match and preg_match_all into one preg_match/preg_match_all.

<?php

$data = 'office phones tel1 6665555998 tel2 555666888 tel3 555688855 home phones tel1 555222555 tel2 555222444 tel3 555666888';

preg_match('/phones(.*)home phones/', $data, $matches); // 1st operation
preg_match_all('/[0-9]{4,12}/',  $matches[1],  $matches); // 2nd operation

var_dump($matches);

// Question is: How to get same output with just only one preg_match

preg_match('/phones(SUBPATTERN)home phones/', $data, $result_data);

// Where SUBPATTERN is a pattern that would do exactly what 2nd operation did
// so $result_data contains what does $matches (array structure can be different can be 3 dimmensional array not only 2)

Example data: https://eval.in/138817

Note: This question is another approach to get answer which had different data: PHP Regular expression return submatches as array

3条回答
Juvenile、少年°
2楼-- · 2019-09-01 01:17

$data = 'office phones tel1 6665555998 tel2 555666888 tel3 555688855 home phones tel1 555222555 tel2 555222444 tel3 555666888';


preg_match_all('/[0-9]{4,12}/', $data,  $matches); // 2nd operation

var_dump($matches);

Like this example

查看更多
Juvenile、少年°
3楼-- · 2019-09-01 01:21

Use positive lookahead (?=.*?home)

<?php

$data = 'office phones tel1 6665555998 tel2 555666888 tel3 555688855 home phones tel1 555222555 tel2 555222444 tel3 555666888';
preg_match_all('/([\d]{2,})(?=.*?home)/', $data, $matches, PREG_PATTERN_ORDER);
print_r($matches[1]);

Array
(
    [0] => 6665555998
    [1] => 555666888
    [2] => 555688855
)

?>

PHP
http://ideone.com/nryjIm

REGEX
http://regex101.com/r/oV7mO2

This is an update based on your comment:

    $pnlist = "office phones tel1 6665555998 tel2 555666888 tel3 555688855 home phones tel1 555222555 tel2 555222444 tel3 555666888";

/*1*/    preg_match_all('/(?:office)(.*?)(?:home)/', $pnlist, $result, PREG_PATTERN_ORDER);
/*2*/    preg_match_all('/([\d]{2,})/', $result[1][0], $pn, PREG_PATTERN_ORDER);

    print_r($pn[1]);

/*
Array ( 
 [0] => 6665555998
 [1] => 555666888
 [2] => 555688855
 ) 
*/

You can change the first preg_match_all start(office) and ending (home) values to whatever you want, then you match the phone numbers on that group.

查看更多
相关推荐>>
4楼-- · 2019-09-01 01:30

You can use the \G anchor with a global research (preg_match_all):

$pattern = '~(?:office phones|\G(?!\A)) tel\d+ \K\d{4,12}~';
preg_match_all($pattern, $data, $matches);

print_r($matches);

\G is an anchor for the position in the string after the last match, when there is not yet match (at the begining) it is equivalent to the \A anchor.

\K is used to remove the left part of the match from match result.

查看更多
登录 后发表回答