регулярное выражение для сопоставления разрывов строк и табуляций между скобками

#php #regex #preg-replace

#php #регулярное выражение #preg-replace

Вопрос:

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

 settings:a [
    a:[
        a:a
        b:b
    ]
    b:[
        a:a
        b:b
    ]
]

settings:b [
    a:[
        a:a
        b:b
    ]
]
 

Таким образом, становится:

 settings:a [ a:[ a:a b:b ] b:[ a:a b:b ] ] 
settings:b [ a:[ a:a b:b ] ]
 

Регулярное выражение, которое я использую n(?=[^[]]*]) , работает в некоторой степени, но я не получаю результат, как указано выше. Вы можете помочь?

Пример регулярного выражения

Комментарии:

1. хотя это работает с регулярным выражением, вам следует подумать о том, чтобы сделать это с php. Если вы посмотрите на регулярное выражение через несколько месяцев … или хуже — если коллега посмотрит на регулярное выражение через несколько месяцев, он не поймет, что вы там сделали

Ответ №1:

Вы можете использовать следующее регулярное выражение с preg_replace (таким образом, будет достаточно одного прохода регулярного выражения):

 [tn] (?=[^][]*(?:([(?:[^][]  |(?1))*])[^][]*)*])
 

Смотрите демонстрацию регулярных выражений. Подробные сведения:

  • [tn] — один или несколько символов табуляции или новой строки (используйте s , если вам нужно сопоставить любые пробелы, а также добавьте u флаг модификатора, если вам нужно обрабатывать тексты в Юникоде)
  • (?=[^][]*(?:([(?:[^][] |(?1))*])[^][]*)*]) — позитивный прогноз, который требует, чтобы его шаблоны соответствовали сразу справа от текущего местоположения:
    • [^][]* — ноль или более символов, отличных от [ и ]
    • (?:([(?:[^][] |(?1))*])[^][]*)* — ноль или более случаев
      • ([(?:[^][] |(?1))*]) — Группа 1 (техническая, необходимая для работы рекурсии): a [ , затем любая подстрока между парными вложенными [ и ] , а затем a ]
      • [^][]* — ноль или более символов, отличных от [ и ]
    • ] ] символ.

Смотрите демонстрацию PHP:

 $re = '/[tn] (?=[^][]*(?:([(?:[^][]  |(?1))*])[^][]*)*])/';
$str = "settings:a [n  a:[n       a:an       b:bn   ]n b:[n       a:an       b:bn   ]n]nnsettings:b [n  a:[n   nna:an       b:bn   ]n]";
echo preg_replace($re, ' ', $str);
// => settings:a [ a:[ a:a b:b ] b:[ a:a b:b ] ]
//    settings:b [ a:[ a:a b:b ] ]
 

Ответ №2:

Вы можете использовать это рекурсивное регулярное выражение в preg_replace_callback :

 $s = 'settings:a [
    a:[
        a:a
        b:b
    ]
    b:[
        a:a
        b:b
    ]
]';

echo preg_replace_callback('/[(?:([^][]*)|(?R))*]/', function ($m) {
      return preg_replace('/s /', ' ', $m[0]); }, $s) . "n";
 

Вывод:

 settings:a [ a:[ a:a b:b ] b:[ a:a b:b ] ]
 

Демонстрация регулярных выражений