我正在寻找一个函数,用于用特定字符替换括号中的一些单词,并将值存储在数组中。我正在寻找这样的东西:
example 1: test(word1,word2)-->test(_,_) -->array[word1,word2]
example 2: test(word1(word11),word2,word3(word33(word333,word3333)))-->test(_,_,_) -->array[word1(word11),word2,word3(word33(word333,word3333))]
我认为您必须逐个字母地遍历字符串。你把每个字母钉在一个缓冲区里。然后你会记录在第一个括号之后你看到了多少个左括号。每次遇到逗号时,都会将字符串的前一部分保存到集合数组中,除非至少遇到一个左括号。在这种情况下,你加上逗号。每次遇到左括号时,递增括号计数器,每次遇到右括号时,递减括号计数器。当括号计数器get回到零(或者在本例中为1)时,您将返回到逗号行为的"保存上一个字符串"。
哦,在执行此操作的同时,当保存上一个字符串时,还会向返回值/output/post-replaced字符串发出一个"_",还会发出逗号等。
至少这是算法的描述,如果你能遵循它,它应该相当简单。
您可以使用以下模式使用preg_match_all
解决问题:regex101
$pattern = <<<'EOD'
~
(?:
'G(?!'A) # contiguous to a previous match
(?: ,| ') 'z (*ACCEPT) ) # a comma or a closing bracket at the string end
| # OR
'A (?<func> 'w+ ) '( # the function name at the start of the string
)
(?:
(?<param> # named capture "param"
(?:
'w+ # param element
(?: # optional part between parenthesis
'(
'g<param> # recursive call to the param subpattern
(?:, 'g<param> )* # optional elements separated by commas
')
)?
)
)
)? # makes the params optional (remove it if you don't want to allow this case)
~x
EOD;
这种模式有两个特点:
标记先前匹配结果的结束并且对于获得连续结果是有用的CCD_ 2锚。(连续结果的优点是提取您想要的信息(作为经典模式),同时检查字符串格式)。
递归。命名的子模式"param"调用自身来处理嵌套的括号。
(*ACCEPT)
是一个回溯控制动词,当它到达时,模式立即成功。
如果字符串格式正确,则会获得不存在捕获"param"的最后一个匹配结果。这是一种方便的方法,可以测试字符串格式从字符串开始到结束是否正确。
让我们看看它在这个示例代码中的作用:ideone
class StrFunc {
private $raw;
private $isBuild = false;
private $funcName;
private $func;
private $params;
private $nbParams;
const PATTERN = '~(?:'G(?!'A)(?:,|')'z(*ACCEPT))|'A(?<func>'w+)'()(?:(?<param>(?:'w+(?:'('g<param>(?:,'g<param>)*'))?)))?~';
public function __construct($raw = null) {
$this->raw = $raw;
if ($raw) $this->createFromRaw();
}
public function createFromRaw() {
if ( !$this->isBuild &&
preg_match_all(self::PATTERN, $this->raw, $m, PREG_SET_ORDER) &&
!isset(end($m)['param']) ) {
$this->params = array_column($m, 'param');
$this->funcName = $m[0]['func'];
$this->nbParams = count($this->params);
$this->func = $this->funcName . '('
. ( ($this->nbParams)
? implode(',', array_fill(1, $this->nbParams, '_'))
: '' )
. ')';
$this->isBuild = true;
}
}
public function setRaw($raw) {
$this->isBuild = false;
$this->raw = $raw;
}
public function getFuncName() {
return ($this->isBuild) ? $this->funcName : $this->isBuild;
}
public function getFunc() {
return ($this->isBuild) ? $this->func : $this->isBuild;
}
public function getParams() {
return ($this->isBuild) ? $this->params : $this->isBuild;
}
};
$tests = array('test(word1,word2)',
'huitre(word1(word11),word2,word3(word33(word333,word3333)))',
'splitz()');
foreach ($tests as $k=>$test) {
$strFunc[$k] = new StrFunc($test);
echo $strFunc[$k]->getFuncName() . "'n"
. $strFunc[$k]->getFunc() . "'n"
. print_r($strFunc[$k]->getParams(), true) . "'n";
}
此示例代码是为PHP 5.5编写的。要使其适应以前的PHP版本,您需要将$this->params = array_column($m, 'param');
替换为:
foreach($m as $match) {
if (isset($match['param']))
$this->params[] = $match['param'];
}
如果您遇到!isset(end($m)['param'])
的问题,您可以将其替换为:
!isset($m[count($m)-1]['param'])