PHP 不使用正则表达式转换字符串
PHP transform string without using regular expression
示例可能效果最好。
a|b|c
需要变成 array('a', 'b', 'c')
a|\||\}
需要变成 array('a', '\|', '\}')
ab\}aaa|ae\|aa
需要变成 array('ab\}aaa', 'ae\|aa')
要转换的字符串可以有任何类型的字符,但是有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}"));
示例可能效果最好。
a|b|c
需要变成array('a', 'b', 'c')
a|\||\}
需要变成array('a', '\|', '\}')
ab\}aaa|ae\|aa
需要变成array('ab\}aaa', 'ae\|aa')
要转换的字符串可以有任何类型的字符,但是有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}"));