【问题标题】:PHP transform string without using regular expressionPHP转换字符串而不使用正则表达式
【发布时间】:2015-08-25 16:46:49
【问题描述】:

示例可能效果最好。

  • a|b|c需要变成array('a', 'b', 'c')
  • a|\||\}需要变成array('a', '\|', '\}')
  • ab\}aaa|ae\|aa 需要变成array('ab\}aaa', 'ae\|aa')

将要转换的字符串可以包含任何类型的字符,但有 3 个“特殊”字符可以解释为简单字符,前提是使用 \ 对其进行转义。 | 分隔选项,但如果转义,则需要将其解释为选项或其一部分(与任何其他字符一样)。 { and } 在这一点上总是会被转义。

问题是我需要在不使用正则表达式的情况下执行此操作。

我已经为此苦苦挣扎了 10 个小时,我当然希望有人对此有一个简单的答案。

***编辑

我的计划是搜索|,如果找到,检查它是否被转义。如果是,则继续搜索下一个。当我找到|时,我会取出字符串的第一个选项,并以同样的方式继续,直到没有|

while ($positionFound != 1) {
            $intPrevPosition = $intPosition;
            $intPosition = strpos($strTemp, '|', $intPosition);
            if ($intPosition === false || (substr_count($strTemp, '|') == 1 && $strTemp{$intPosition + $intPrevPosition - 1} == '\\')) {
                $arrOptions[] = $strTemp;
                $positionFound = 1;
            }
            elseif ($strTemp{$intPosition + $intPrevPosition - 1} != '\\') {
                $intPosition = $intPrevPosition + $intPosition;
                $arrOptions[] = substr(substr($strTemp, 0, $intPosition + 1), 0, -1);
                $strTemp = substr($strTemp, $intPosition + 1);
                $intPosition = 0;
            }
        }

【问题讨论】:

  • 为什么不能使用正则表达式? preg_split 是正确的工具。
  • 如果这是一些没有实际用途的家庭作业问题,并且您已经尝试了 10 个小时的解决方案 - 那么至少分享其中一个,或者您对如何解决的想法接近它。
  • 这是作业的一部分,它禁止使用正则表达式。我已经到了它的最后一部分,但现在我被卡住了。

标签: php arrays string escaping


【解决方案1】:

编写一个简单的解析器:

$input = "ab\\}aaa|ae\\|aa"; // ab\}aaa|ae\|aa

$token = "";
$last_char = "";
$len = strlen($input);
$tokens = array();
for ($i = 0; $i < $len; $i += 1) {
    $char = $input[$i];
    if ($char === "|" && $last_char !== "\\") {
        $tokens[] = $token;
        $token = "";
    }
    $token .= $char;
    $last_char = $char;
}
$tokens[] = $token; // capture last token
var_dump($tokens);
// array('ab\}aaa', 'ae\|aa')

请注意,在此实现中,转义还会触发:ab\\|cd,输出为array("ab\\|cd") 而不是array("ab\\", "cd")


嵌套解析器

为了便于理解,我暂时忘记\ 规则。

假设您有:a{b|c}|{d|e},预期输出为:abd, abe, acd, ace

首先你要做的是将a{b|c}|{d|e}翻译成:

array(
    "a",
    array("b", "c")
    array("d", "e")
)

如果输入是ab{cd|ef}|{gh|ij},我们想要:

array(
    "ab",
    array("cd", "ef")
    array("gh", "ij")
)

当然,多层嵌套也应该起作用:a{b|{c|d}}|e

array(
    "a",
    array("b", array("c", "d"))
    "e"
)

这里是解析函数。我还没有完全弄清楚如何将它重新组合在一起

function parse($string, $i = 0) {
    $token = "";
    $tokens = array();
    for (; $i < strlen($string); $i += 1) {
        $char = $string[$i];
        if ($char === "{") {
            if ($token !== "") {
                $tokens[] = $token;
            }
            $token = "";
            $parse = parse($string, $i + 1);
            $tokens[] = $parse["token"];
            $i = $parse["index"];
            continue;
        }
        if ($char === "}") {
            // end of this part
            if ($token !== "") {
                $tokens[] = $token;
            }
            return array(
                "token" => $tokens,
                "index" => $i
            );
        }
        if ($char === "|") {
            if ($token !== "") {
                $tokens[] = $token;
            }
            $token = "";
            continue;
        }
        $token .= $char;
    }
    return $tokens;
}
var_dump(parse("ab{cd|ef}|{gh|ij}"));

【讨论】:

  • 我明白了。让我想想办法。
  • 原谅我,Halcyon,嵌套是这个项目不同部分的问题。这个解析器工作得很好。感谢您的大力帮助!
  • 我明白了,我正在处理嵌套解析器的事情。我发布了我所拥有的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-06
  • 2018-10-30
  • 2021-09-16
  • 2018-12-30
  • 2015-04-13
相关资源
最近更新 更多