어디선가 본 '재귀호출을 이용하지 않는' 내부중첩 괄호 추출법


$sStr = '(1(2(3)(4(5)4)2)1)';
$i = 0;
while (preg_match("/\([^()]*\)/", $sStr, $aMatches)) {
    $aRe[$i] = $aMatches[0];
    $sStr = str_replace($aMatches[0], '^!__R_'.$i.'__!^', $sStr);
    ++$i;
}

var_dump($aRe, $sStr);

// 결과는 아래와 같음
array
  0 => string '(3)' (length=3)
  1 => string '(5)' (length=3)
  2 => string '(44)' (length=4)
  3 => string '(22)' (length=4)
  4 => string '(11)' (length=4)
string '' (length=0)




다음은 거기에 재귀호출을 이용한 뻘짓거리.
같은 레벨의 중첩괄호 안의 문자열에 랜덤색상 입히기

// 단지 무작위 색 반환
function getRandomColor()
{
    for ($i=0; $i<3; $i++) $sColor .= dechex(rand(0,255));
    return '#'.$sColor;
}

// 치환(재귀호출)
function substitute($a, $s)
{
    // 내부 중첩 괄호를 제외한 현재 레벨의 문자열에 특정 색을 부여
    preg_match_all("/(\^!__R_[\d]{1,}__!\^)/", $s, $aR);
    $aTmp = preg_split("/\^!__R_[\d]{1,}__!\^/", $s);
    $sTmp = '';
    $sColor = getRandomColor();
    foreach ($aTmp as $k=>$v) {
        if (strlen(trim($v))>0) $sTmp .= '<font color="'.$sColor.'">'.$v.'</font>';
        $sTmp .= $aR[0][$k];
    }
    $s = $sTmp;

    // 만약 내부 중첩괄호가 있다면 재귀호출
    preg_match_all("/\^!__R_([\d]{1,})__!\^/s", $s, $aMatches);
    if (count($aMatches[0])>0) {
        foreach ($aMatches[0] as $k=>$v) {
            $s = str_replace($v, substitute($a, $a[$aMatches[1][$k]]), $s);
        }
    }
    return $s;
}

function test()
{
    // 기준 문자열
    $sStr = 'aaa(bbb(ccc(ddd)(eee(fff)eee)ccc)(ggg(hhh(iii)hhh)(jjj)ggg)bbb)aaa';

    // 중첩괄호를 뽑아내며 모음
    $i = 0;
    while (preg_match("/\([^()]*\)/", $sStr, $aMatches)) {
        $aRe[$i] = $aMatches[0];
        $sStr = str_replace($aMatches[0], '^!__R_'.$i.'__!^', $sStr);
        ++$i;
    }

    // 같은 레벨의 괄호문자열들에 뭔짓이든 함
    echo substitute($aRe, $sStr);
}

// 호출해서 브라우저로 확인해보기
test();
Posted by bloodguy
,