У меня есть поле ввода в форме, которую я должен проверить для определенной разметки, которую мы настроили.

Разделитель: {!, }.

Я хотел бы сопоставить все, что находится внутри разделителей.

content = /regex/g.exec('{!content}')

Кроме того, входная строка может содержать более одной разметки.

input = '{!content} {!other}';
['content','other'] = /regex/g.exec('{!content} {!other}')

Это первая часть проблемы, теперь самое интересное.

У меня также есть случаи, когда определенные разделители разметки не заканчиваются правильно, и я должен проверить их тоже.

В этом случае я хотел бы получить:

input = '{!content {!other} {!broken';
['{!content', 'other', '{!broken'] = /regex/g.exec(input);

Обновление * обнаружило случай, когда оригинальное решение от @MikeM не захватывает то, что мне хотелось бы. Если начальный разделитель сам по себе, он должен отображаться в массиве результатов. Если начальный разделитель находится в конце строки, он не будет записан.

input = '{!content {!other} {!';
['{!content', 'other', '{!'] = /regex/g.exec(input);
0
Bruce Lim 2 Фев 2013 в 03:09

2 ответа

Лучший ответ

Вы можете использовать следующее, если { и } не разрешены в контенте

var m,    
    result = [],
    str = '{!content {!other} {!broken',
    reg = /\{!([^{}]+)\}|(\{![^{}]+)/g;

while ( m = reg.exec( str ) ) {
    result.push( m[1] || m[2] );
}

console.log( result );   // [ "{!content ", "other", "{!broken" ]

Тем не менее, было бы захватить пробелы после закрытого контента.

Обновление:

Для захвата контента без включения начальных или конечных пробелов вы можете использовать следующее - написанное в более длинной форме для ясности.

var m,    
    result = [],
    str = '{!content {!other} {!broken  {!    broken {! content }',
    reg = /\{!\s*([^{}]+?)\s*\}|\{!\s*([^{}]+?)\s*(?=\{|$)/g;

m = reg.exec( str );

while ( m != null ) {   

    if ( m[1] != null ) {
        result.push( m[1] );
    } else {  // m[2] cannot be null
        result.push( '{!' + m[2] );
    }
    m = reg.exec( str );
}

console.log( result );   
// [ "{!content", "other", "{!broken", "content", "{!broken", "content" ]

Подробнее о exec см. MDN exec .

2
MikeM 2 Фев 2013 в 09:37

Возвращает массив совпадений:

(str.match(/\{\!.*?.(?=[\{\}])|\{\!.+?$/g)||[]).map(function(m){return m.substring(2);});
  • (_.match(...)||[]) это идиома. Match возвращает null, если совпадение не найдено, но обычно удобнее получить пустой массив. ||[] исправляет это.

  • Регулярное выражение находит соответствия между {! и терминаторами не жадным образом. То есть он ищет первое }, которое он может найти после {!. Мы также должны быть терпимы к несоответствующей открытой скобке { и концу строки и пропустить их через возможные совпадения.

    введите описание изображения здесь

  • Совпадения из приведенного выше всегда начинаются с {!, но не имеют завершающего разделителя. Осталось только очистить его, чтобы мы могли map поместить массив в substring(2). Если вы хотите избавиться от пробелов до и после, вы можете сделать это substring(2).trim().

0
Community 20 Июн 2020 в 09:12