【问题标题】:Get string between every two certain characters with PHP使用PHP获取每两个特定字符之间的字符串
【发布时间】:2019-05-12 06:49:27
【问题描述】:

我有这样的字符串:

The time is over. # its mean I'm need to die. Please help me. # Ghost. I am here alone. Sorry. # help yourself.

我想获取每个 # 和点 (.) 之间的文本 所以我用这个:

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);
}

$parsed = trim(get_string_between($url, '#', '.'));
echo $parsed;

问题在于该函数仅返回与我的查询匹配的第一个示例。对于我选择的每个查询,我没有任何想法。

在这个示例字符串中它需要返回这个:

its mean I'm need to die

Ghost

help yourself

编辑@Nick Answer

我真正的字符串是这样的:

Text Text Text # Very good. #:* after this come example. Text Text Text #Very good number 2.

您的代码还返回了#:* 之后的字符串,我只需要这些示例: # Text Text. #Text Text.

在给定的示例中,我需要获取以下文本:

Very goodVery good number 2

【问题讨论】:

  • 你的问题描述真的不清楚。在每个 #. 之间?这意味着您在第一个示例字符串中的匹配项将是 (space)its mean I'm need to die 对吗?
  • 您希望第二个结果是“Ghost”还是“Ghost。我一个人在这里”?因为即使通过文本循环您的函数,您仍然会遇到所需文本内部有句点的问题。也许更好的方法是找到# 和换行符之间的文本?
  • 不,我现在只是编辑问题以使其清楚。 @Xatenev 查看编辑
  • @JaredC 否,因为查询文本可以在文本中间。
  • 所以你复制了答案here 没有自己尝试任何东西并寻求人们的帮助?我称之为懒惰。

标签: php


【解决方案1】:

更新

根据 OP 编辑​​,需要更改正则表达式,以便在 # 之后立即对空格或字母字符使用正向预读,即

/#(?=[ A-Za-z])\s*([^.]*)\./

要使用编辑中的文本:

$string = "Text Text Text # Very good. #:* after this come example. Text Text Text #Very good number 2.";
preg_match_all('/#(?=[ A-Za-z])\s*([^.]*)\./', $string, $matches);
print_r($matches[1]);

输出

Array
(
    [0] => Very good
    [1] => Very good number 2
)

更新demo on rextester

原答案

您可以使用preg_match_all 来获得您想要的结果。此正则表达式在 #. 之间查找一组字符,通过使用非贪婪捕获组和捕获组两侧的 \s* 去除两端的任何空格:

$string = "The time is over. # its mean I'm need to die .
Please help me. # Ghost. I am here alone.
Sorry. # help yourself.";
preg_match_all('/#\s*([^.]*?)\s*\./', $string, $matches);
print_r($matches[1]);

输出:

Array
(
    [0] => its mean I'm need to die
    [1] => Ghost
    [2] => help yourself
)

Demo on rextester

【讨论】:

  • 工作完美,但仅在第一个,因为我的字符串与我给定的示例不同。我现在编辑帖子。
  • @Ben 所以# 后面只能有空格或字母字符,对吗?
  • 是的,完全正确。例如:# text.#text. 但不是 #:* text.
  • @Ben 我认为我编辑的答案将解决该问题。
  • 可以在$matches[1]上进行foreach吗?
【解决方案2】:

explodesubstrstrpos 的组合可以做到:

#分割字符串,然后使用substrstrpos得到#和第一个.之间的字符串。

<?php

$examples = [
    'The time is over. # its mean I\'m need to die.',
'Please help me. # Ghost. I am here alone.',
'Sorry. # help yourself.'];

foreach($examples as $example) {
    $exploded = explode('#', $example);
    $substr = trim(substr($exploded[1], 0, strpos($exploded[1], '.')));
    var_dump($substr);
}

在一个特定字符串的函数中:

$test = parseString('Sorry. # help yourself.');
function parseString($string) {
    $exploded = explode('#', $string);
    $substr = trim(substr($exploded[1], 0, strpos($exploded[1], '.')));

    return $substr;
}

var_dump($test);

对于字符串输入,我们必须执行一个额外的步骤,该步骤之前被\n 打破:

$stringExample = "The time is over. # its mean I'm need to die.
Please help me. # Ghost. I am here alone.
Sorry. # help yourself.";


$test2 = parseString2($stringExample);
function parseString2($string) {
    $result = [];
    $array = explode("\n", $string);

    foreach($array as $a) {
        $exploded = explode('#', $a);
        $substr = trim(substr($exploded[1], 0, strpos($exploded[1], '.')));    
        $result[] = $substr;
    }

    return $result;
}
var_dump($test2);

对于没有换行符的字符串输入,一个小解析器可能如下所示:

$stringExample2 = "The time is over. # its mean I'm need to die. Please help me. # Ghost. I am here alone. Sorry. # help yourself.";


var_dump(parseString3($stringExample2));
function parseString3($stringExample)
{
    $result2 = [];

    $startBlock = false;

    $block = 0;
    foreach (str_split($stringExample) as $char) {
        if ($char === '#') { // Start block
            $startBlock = true;
        } else if ($startBlock && $char === '.') { // End block
            $result2[$block] = trim($result2[$block]); // Remove unnecessary whitespace
            $block++;
            $startBlock = false;
        } else if ($startBlock) { // Character to append to block
            if (!isset($result2[$block])) { // We have to check if the block has been started already and if not, create it as an empty string because otherwise we would get a notice when trying to append our character to it.
                $result2[$block] = '';
            }
            $result2[$block] .= $char;
        }

    }
    return $result2;
}

如果您使用此代码中的任何一个,请确保真正了解正在发生的事情并使用适当的变量名,这些只是 sn-ps 的小示例。

所有示例及其输出都可以在下面的 3v4l 链接中找到

https://3v4l.org/k3TXM

【讨论】:

  • 不是字符串数组,只是字符串
  • @executable ?我正在遍历 OP 中的示例。我将添加一个带有特定字符串的示例,但我不明白为什么需要它
  • @Xatenev 非常感谢您的帮助。正如他所说,我的问题在于没有数组的字符串 - 我尝试你过去发送的内容。
  • @executable 哦,我明白你的意思了。
  • @Xatenev 抱歉,但正如我在问题中所说,我的问题与我的示例一样的多个查询有关。我的意思是 - 超过 1 个。
猜你喜欢
  • 1970-01-01
  • 2013-03-16
  • 2013-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
  • 1970-01-01
相关资源
最近更新 更多