2

コンマを含む文字列を分割する必要があります。私はすでに ( str_getcsv) のような文字列の何かを見つけました:

'A', 'B with a comma, eh', 'C'

しかし、私の文字列は次のようになります。たとえば、値を囲む文字はありません。

A, B (one, two), C

これを分解して取得する必要があります:

array(3) {
  [0]=>
  string(1) "A"
  [1]=>
  string(12) "B (one, two)"
  [2]=>
  string(1) "C"
}

括弧内にないコンマを使用して文字列を分割したいのは、爆発が失敗したときの私の状況で唯一のケースだからです。

4

3 に答える 3

5

しかし、あなたのクレイジーな願いには解決策があります ;)

$a = "(Z) X, (Y, W) A, B (one, two), C, D (E,F,G) H, I J";
$reg = '/[^(,]*(?:\([^)]+\))?[^),]*/';
preg_match_all($reg, $a, $matches);
$result = array_filter($matches[0]);
var_dump($result);
于 2012-06-16T09:40:13.213 に答える
1

このスニペットは、ネストされた括弧で役立ちます。基本的なアイデアは、括弧がなくなるまで (*) を何らかの識別子に再帰的に置き換えることです。次に、文字列をコンマで分解してから、すべてを元に戻します。これは理想的な解決策ではありません - たった今約 30 分で作成しましたが、うまくいきます :) 何らかの形で最適化できることは間違いありません。

/**
 * Explode string by delimiter, but don't explode if delimiter is inside parenthesis.
 * This also support nested parenthesis - that's where pure RegExp solutions fails.
 * 
 * For example,
 *  $input = "one, two three, four (five, (six, seven), (eight)) (nine, ten), eleven";
 *  $output = array(
 *      'one',
 *      'two three',
 *      'four (five, (six, seven), (eight)) (nine, ten)',
 *      'eleven'
 *  );
 * 
 * @param string $input
 * @param string $delimiter = ,
 * @param string $open_tag = \(
 * @param string $close_tag = \)
 * @return array
 */
function exploder($input, $delimiter = ',', $open_tag = '\(', $close_tag = '\)')
{
    // this will match any text inside parenthesis
    // including parenthesis itself and without nested parenthesis
    $regexp = '/'.$open_tag.'[^'.$open_tag.$close_tag.']*'.$close_tag.'/';

    // put in placeholders like {{\d}}. They can be nested.
    $r = array();
    while (preg_match_all($regexp, $input, $matches)) {
        if ($matches[0]) {
            foreach ($matches[0] as $match) {
                $r[] = $match;
                $input = str_replace($match, '{{'.count($r).'}}', $input);
            }
        } else {
            break;
        }
    }
    $output = array_map('trim', explode($delimiter, $input));

    // put everything back
    foreach ($output as &$a) {
        while (preg_match('/{{(\d+)}}/', $a, $matches)) {
            $a = str_replace($matches[0], $r[$matches[1] - 1], $a);
        }
    }

    return $output;
}

$a = "one, two three, four (five, (six, seven), (eight)) (nine, ten), eleven";
var_dump(exploder($a));

これは出力されます:

array (size=4)
  0 => string 'one' (length=3)
  1 => string 'two three' (length=9)
  2 => string 'four (five, (six, seven), (eight)) (nine, ten)' (length=46)
  3 => &string 'eleven' (length=6)

予想通り。

于 2013-03-25T00:17:26.720 に答える