2016-06-01 2 views
3

Мне нужно определить, содержит ли строка какие-либо незакрытые угловые скобки.PHP regexp - обнаружение незакрытых скобок

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

if (substr_count($string, '<') !== substr_count($string, '>')) 
{ 
    // Text contains unclosed angle brackets   
} 

Но этот метод не обнаружит ошибку, как это:

This is >b<BOLD>/b< word 
+0

html? то вы можете попробовать следующее: http://stackoverflow.com/questions/3167074/which-function-in-php-validate-if-the-string-is-valid-html – jbe

+0

Пожалуйста, проверьте ответы и подумайте о том, чтобы принять тот, который работает лучше всего для вас/повышая эффективность тех, которые вы найдете полезными. Или дайте дополнительные разъяснения в теле вашего вопроса. –

ответ

2

Я бы не рекомендовал использовать регулярные выражения для такой задачи.
Простая функция, чтобы проверить строку для правильно написанных скобок быстро написана:

/** 
* @param $str input string 
* @returns boolean true if all brackets are properly opened and closed, false otherwise 
*/ 
function checkBraces($str) 
{ 
    $strlen = strlen($str); // cache string length for performance 
    $openbraces = 0; 

    for ($i = 0; $i < $strlen; $i++) 
    { 
     $c = $str[$i]; 
     if ($c == '<') // count opening bracket 
      $openbraces++; 
     if ($c == '>') // count closing bracket 
      $openbraces--; 

     if ($openbraces < 0) // check for unopened closing brackets 
      return false; 
    } 

    return $openbraces == 0; // check for unclosed open brackets 
} 

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

+0

* «Я бы не рекомендовал использовать регулярные выражения для такой задачи.» *, По какой причине? –

+0

* «Простая функция проверки строки для правильно написанных скобок быстро записывается» * и выполняется медленнее. –

+0

@CasimiretHippolyte применимость регулярных выражений к HTML и подобным языковым конструкциям неоднократно обсуждалась на этом веб-сайте, я уверен, что вы можете найти эти потоки. Если производительность вас беспокоит, PHP - это неправильный инструмент для начала. –

2

Но этот метод не будет обнаружить такую ​​ошибку:

Потому что подсчет делает если вы хотите проверить, существует ли равное количество открывающих и закрывающих скобок. Но если вы хотите быть добрым к своему пользователю и указать на место, которое он допустил ошибку, то подсчета будет недостаточно, и вы должны использовать, то есть стек (даже на основе массива на основе array_push() и array_pop()). С помощью стека вы перебираете строку и нажимаете токен, когда вы сталкиваетесь с открывающей скобкой < и вытаскиваете токен, когда вы нажимаете на закрытие >. В вашем случае:

This is >b<BOLD>/b< word 

вы должны сделать pop, как первый является >, но нет ничего в стек, это вызывает ошибку. Давайте исправим эту скобу и продолжить:

This is <b<BOLD>/b< word 

и запустить

push -> ok 
push -> well if you allow nested brackets, then all is ok, otherwise 
     stack must be empty prior pushing so this bracket is misplaced 
     and you shall throw an error 

и так далее ... и как только вы достигнете конца строки и ваш стек не пуст, то вы знаете, в последний раз замечен < промаха его пара > (Если вы разрешаете вложение скобок, то логика, необходимая для указания того, какой из них потенциально не закрыт, может быть более сложной и иногда давать ложные результаты (например, иногда компиляторы делают в подобном случае)).

Если вы не планируете, чтобы вложенные скобки, то вы можете сделать ваш код еще проще, так как при использовании обычной integer переменной для индикации состояния будет достаточно (т.е. «0» для <, 1 для > и -1 для начального состояния)

1

Прокрутите строку по одному символу за раз, если символ «<» увеличит счетчик, и если он «>» уменьшает счетчик. Если счетчик когда-либо становится отрицательным или счетчик не равен нулю, когда вы проходите через строку, то у вас есть закрытые скобки.

+0

'тогда у вас есть закрытые скобки', но вы все еще не знаете где. –

+0

Вопрос только в том, чтобы определить, есть ли закрытые скобки, а не где они. – Schleis

1

Существует регулярное выражение PCRE, чтобы проверить правильность ряда сбалансированных угловых скобках:

'~\A[^<>]*+(<(?>[^<>]|(?1))*+>[^<>]*+)++\z~' 

ВИДЕТЬ regex demo

Просмотреть контактные данные на странице Matching Balanced Constructs на обычном сайте-expressions.info.

Вкратце:

  • \A - начало строки
  • [^<>]*+ - ноль или больше символов, отличных от < и >
  • (<(?>[^<>]|(?1))*+>[^<>]*+)++ - 1 или более вхождений
    • < - открытие < скоба
    • (?>[^<>]|(?1))*+ - 0 или более вхождений любого полукокса, кроме < и > (см [^<>]) или вся группа 1 подмаски (вызов подпрограммы (?1))
    • > - закрытие > кронштейн
    • [^<>]*+ - ноль или более символов других чем < и >
  • \z - конец строки.
-1

Вот регулярное выражение, которое не допускает вложенные скобки.

/^([^<>]*<[^>]*?>[^<>]*)*$/m 
Смежные вопросы