PHP 不使用正则表达式转换字符串

PHP transform string without using regular expression

示例可能效果最好。

要转换的字符串可以有任何类型的字符,但是有3个"special"字符可以被解释为一个简单的字符,只有用\转义。 | 分隔一个选项,但如果转义,则需要被解释为一个选项或其一部分(与任何其他字符一样)。 { 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;
            }
        }

编写一个简单的解析器:

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