PHP и RegEx: Разделите строку запятыми, которые не являются внутренними скобками (и также вложенными скобками)

К моему опыту в большинстве SQL Server нет никакого резервного копирования журнала транзакций. Полное резервное копирование или дифференциальное резервное копирование являются обычной практикой, но резервные копирования журнала транзакций действительно редко. Таким образом, файл журнала транзакций растет навсегда (пока диск не полон). В этом случае модель восстановления должна быть установлена на" простой ". Не забывайте изменять системные базы данных "модель" и "tempdb", также.

резервное копирование А базы данных "tempdb" не имеет никакого смысла, таким образом, модель восстановления этого дб должна всегда быть "простой".

7
задан Cristian Toma 28 July 2009 в 15:15
поделиться

7 ответов

Вы можете сделать это проще:

preg_match_all('/[^(,\s]+|\([^)]+\)/', $str, $matches)

Но было бы лучше, если бы вы использовали настоящий синтаксический анализатор. Может быть, что-то вроде этого:

$str = 'one, two, three, (four, (five, six), (ten)), seven';
$buffer = '';
$stack = array();
$depth = 0;
$len = strlen($str);
for ($i=0; $i<$len; $i++) {
    $char = $str[$i];
    switch ($char) {
    case '(':
        $depth++;
        break;
    case ',':
        if (!$depth) {
            if ($buffer !== '') {
                $stack[] = $buffer;
                $buffer = '';
            }
            continue 2;
        }
        break;
    case ' ':
        if (!$depth) {
            continue 2;
        }
        break;
    case ')':
        if ($depth) {
            $depth--;
        } else {
            $stack[] = $buffer.$char;
            $buffer = '';
            continue 2;
        }
        break;
    }
    $buffer .= $char;
}
if ($buffer !== '') {
    $stack[] = $buffer;
}
var_dump($stack);
11
ответ дан 6 December 2019 в 06:14
поделиться

Вы не можете напрямую. Вам понадобится, как минимум, ретроспективный просмотр переменной ширины, и, наконец, я знал, что PHP PCRE имеет только ретроспективный просмотр фиксированной ширины.

Моя первая рекомендация - сначала извлечь выражения в скобках из строки. Однако я ничего не знаю о вашей реальной проблеме, поэтому не знаю, возможно ли это.

5
ответ дан 6 December 2019 в 06:14
поделиться

Я не могу придумать способ сделать это с помощью одного регулярного выражения, но довольно легко собрать что-то, что работает:

function process($data)
{
        $entries = array();
        $filteredData = $data;
        if (preg_match_all("/\(([^)]*)\)/", $data, $matches)) {
                $entries = $matches[0];
                $filteredData = preg_replace("/\(([^)]*)\)/", "-placeholder-", $data);
        }

        $arr = array_map("trim", explode(",", $filteredData));

        if (!$entries) {
                return $arr;
        }

        $j = 0;
        foreach ($arr as $i => $entry) {
                if ($entry != "-placeholder-") {
                        continue;
                }

                $arr[$i] = $entries[$j];
                $j++;
        }

        return $arr;
}

Если вы вызовете это как это:

$data = "one, two, three, (four, five, six), seven, (eight, nine)";
print_r(process($data));

Он выводит:

Array
(
    [0] => one
    [1] => two
    [2] => three
    [3] => (four, five, six)
    [4] => seven
    [5] => (eight, nine)
)
2
ответ дан 6 December 2019 в 06:14
поделиться

Неуклюжий, но он выполняет свою работу ...

<?php

function split_by_commas($string) {
  preg_match_all("/\(.+?\)/", $string, $result); 
  $problem_children = $result[0];
  $i = 0;
  $temp = array();
  foreach ($problem_children as $submatch) { 
    $marker = '__'.$i++.'__';
    $temp[$marker] = $submatch;
    $string   = str_replace($submatch, $marker, $string);  
  }
  $result = explode(",", $string);
  foreach ($result as $key => $item) {
    $item = trim($item);
    $result[$key] = isset($temp[$item])?$temp[$item]:$item;
  }
  return $result;
}


$test = "one, two, three, (four, five, six), seven, (eight, nine), ten";

print_r(split_by_commas($test));

?>
2
ответ дан 6 December 2019 в 06:14
поделиться

Боюсь, что будет очень сложно разобрать вложенные скобки, например один, два, (три, (четыре, пять)) только с RegExp.

1
ответ дан 6 December 2019 в 06:14
поделиться

I feel that its worth noting, that you should always avoid regular expressions when you possibly can. To that end, you should know that for PHP 5.3+ you could use str_getcsv(). However, if you're working with files (or file streams), such as CSV files, then the function fgetcsv() might be what you need, and its been available since PHP4.

Lastly, I'm surprised nobody used preg_split(), or did it not work as needed?

1
ответ дан 6 December 2019 в 06:14
поделиться

Хм ... ОК, уже помечено как ответ, но так как вы просили простое решение, я все же попробую:

<?php
  $test = "one, two, three, , , ,(four, five, six), seven, (eight, nine)";
  $split = "/([(].*?[)])|(\w)+/";
  preg_match_all($split, $test, $out);
  print_r($out[0]);              
  die();
?>

Output

Array
(
    [0] => one
    [1] => two
    [2] => three
    [3] => (four, five, six)
    [4] => seven
    [5] => (eight, nine)
)
7
ответ дан 6 December 2019 в 06:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: