в javascript невозможно заменить () с помощью дополнительного соответствия

#javascript #regex

#javascript #регулярное выражение

Вопрос:

хотите избежать всех вхождений «.» и «:» в квадратных скобках

 [ab:1.2:ef]='12.3' => [ab:1.2:ef]='12.3'
  

пробовал различные перестановки replace , например,

 str.replace( /([.*)(.|:)(.*])/g, '1\23' );
  

но никакой радости.


Оба ответа правильные и не только.

Первое, чистое совпадение с шаблоном, выполняет свою работу и является очень кратким. На мой взгляд, это лучше отвечает на поставленный вопрос.

Второй, вызываемый replace с помощью функции arg, немного более надежный и предлагает значительно большую гибкость. В моем коде используется этот подход, потому что он легко обрабатывает пару особых случаев.

Ответ №1:

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

 result = subject.replace(/([:.])(?=[^[]]*])/g, "\$1");
  

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

 ([:.])    # Match and remember a dot/colon,
(?=       # only if it is followed by:
 [^[]]*  # any number of characters excluding brackets,
 ]       # followed by a closing bracket.
)         # End of lookahead assertion.
  

Предварительный просмотр гарантирует, что следующая скобка после точки / двоеточия, на которую мы смотрим, является закрывающей скобкой.

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

1. отличное объяснение. меня удивило, что вы не беспокоитесь о начальной скобке (поскольку она должна быть там) — делает сопоставление менее сложным.

2. Это не требует как открывающей, так и закрывающей фигурной скобки. Таким образом, это не работает для: [ab:1.2:ef]='12.3]' или ab:1.2:ef]='12.3' .

3. Правильно, вот почему я написал, что скобки должны быть правильно сбалансированы (JavaScript не поддерживает утверждения lookbehind). Я должен добавить, что это также касается скобок внутри строк, комментариев и т. Д.

Ответ №2:

Я знаю только, как это сделать с помощью функции replace:

 var test = "[ab:1.2:ef]='12.3'";

var out = test.replace(/[.*?]/g, function(str) {
    return(str.replace(/.|:/g, "\$amp;"));
});

// out is [ab:1.2:ef]='12.3'
  

Посмотрите это в действии здесь: http://jsfiddle.net/jfriend00/ZHVjW /

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

1. вау! никогда не видел функцию, используемую в качестве аргумента в replace — очень круто. намного элегантнее, чем match цикл, который использовался ранее. Спасибо!

2. Что касается вашего комментария к моему ответу, у вашего регулярного выражения также будут проблемы с несбалансированными скобками в строках, подобных [ab:1.2] = '[12.3'; [cd:3.4] = '34.5]' . Как только разделители не сбалансированы и / или внутри строк / комментариев, регулярные выражения начинают завершаться сбоем, и для такой работы вам нужен синтаксический анализатор.

3. Да, тонкая грань между выполнением работы и выводом большого железа. Тем не менее, знаете ли вы утилиту, которая преобразует (несколько) произвольную строку в древовидную структуру польского типа?

4. @TimPietzcker — пример, на который вы указываете, — это вложенные скобки. В OP не указано, что вложенные скобки являются обязательным требованием. Решение для вложенных было бы намного сложнее (вероятно, не просто проблема с регулярными выражениями) при любом подходе. Мне просто показалось странным, что ваше решение не требует какой-либо открытой скобки. Если с этим все в порядке, ничего страшного.

5. Какие вложенные скобки? Это было бы дополнительной проблемой (для всех наших регулярных выражений); здесь внутри строк просто скобки. Проблема осталась бы идентичной [ab:1.2] = '[12.3'; [cd:3.4] = '34.5' .