3

当然,这已经被其他人问过了,但是我在 SO 上搜索过这里并没有找到任何东西https://stackoverflow.com/search?q=php+parse+between+words

我有一个字符串,想要获得一个包含 2 个分隔符(2 个单词)之间的所有单词的数组。我对正则表达式没有信心,所以我最终得到了这个解决方案,但这并不合适,因为我需要获得所有符合这些要求的单词,而不仅仅是第一个。

$start_limiter = 'First';
$end_limiter = 'Second';
$haystack = $string;

# Step 1. Find the start limiter's position

$start_pos = strpos($haystack,$start_limiter);
if ($start_pos === FALSE)
{
    die("Starting limiter ".$start_limiter." not found in ".$haystack);
}

# Step 2. Find the ending limiters position, relative to the start position

$end_pos = strpos($haystack,$end_limiter,$start_pos);

if ($end_pos === FALSE)
{
    die("Ending limiter ".$end_limiter." not found in ".$haystack);
}

# Step 3. Extract the string between the starting position and ending position
# Our starting is the position of the start limiter. To find the string we must take
# the ending position of our end limiter and subtract that from the start limiter
$needle = substr($haystack, $start_pos+1, ($end_pos-1)-$start_pos);

echo "Found $needle";

我也想过使用 explode() 但我认为正则表达式可能会更好更快。

4

5 回答 5

8

我对 PHP 不太熟悉,但在我看来,你可以使用类似的东西:

if (preg_match("/(?<=First).*?(?=Second)/s", $haystack, $result))
    print_r($result[0]);

(?<=First)寻找First但不消耗它,

.*?捕获介于First和之间的所有内容Second

(?=Second)向前看,Second但不消耗它,

最后s是使点.匹配换行符(如果有)。


要获取这些分隔符之间的所有文本,您可以使用preg_match_all并且可以使用循环来获取每个元素:

if (preg_match_all("/(?<=First)(.*?)(?=Second)/s", $haystack, $result))
    for ($i = 1; count($result) > $i; $i++) {
        print_r($result[$i]);
    }
于 2013-08-12T18:35:37.740 回答
3

这允许您使用不同的参数运行相同的函数,这样您就不必一直重写这段代码。还使用您使用的 strpos。一直对我很好。

function get_string_between($string, $start, $end){
    $string = " ".$string;
    $ini = strpos($string,$start);
    if ($ini == 0) return "";
    $ini += strlen($start);
    $len = strpos($string,$end,$ini) - $ini;
    return substr($string,$ini,$len);
}

$fullstring = 'This is a long set of words that I am going to use.';

$parsed = get_string_between($fullstring, 'This', "use");

echo $parsed;

将输出:

is a long set of words that I am going to
于 2013-08-13T06:44:11.963 回答
3

不确定结果是否会比您的代码更快,但您可以使用正则表达式执行此操作:

$pattern = '~(?<=' . preg_quote($start, '~') 
         . ').+?(?=' . preg_quote($end, '~') . ')~si';
if (preg_match($pattern, $subject, $match))
    print_r($match[0]);

我使用preg_quote来转义在正则表达式中具有特殊含义的所有字符(例如+*|()[]{}.?和模式分隔符~

(?<=..)是一个lookbehind 断言,它在您想要查找的内容之前检查子字符串。
(?=..)是一个前瞻断言(同样的事情)
.+?意味着所有字符一次或多次,但可能性较小(问号使量词变得懒惰)

s允许点匹配换行符(不是默认行为)
i使搜索不区分大小写(如果不需要,可以将其删除)

于 2013-08-12T18:34:28.343 回答
2

这是一个简单的示例,用于查找字符串 'mega' 和 'yo' 之间的所有内容$t

PHP 示例

$t = "I am super mega awesome-sauce, yo!";

$arr = [];
preg_match("/mega\ (.*?)\ yo/ims", $t, $arr);

echo $arr[1];

PHP 输出

awesome-sauce,
于 2013-08-12T18:35:26.917 回答
0

您还可以使用两个爆炸语句。

例如,假设您想在 y=mx^z+b 中得到“z”。要获得 z:

$formula="y=mx^z+b";
$z=explode("+",explode("^",$formula)[1])[0];

首先,我在 ^ 之后得到所有内容:explode("^",$formula)[1]

然后我得到 + 之前的所有内容:explode("+",$previousExplode)[0]

于 2016-01-14T14:26:48.083 回答