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

Я безуспешно пытаюсь избежать ссылки на член MDX с помощью RegEx.

Это входная строка:

[dim[e]nsion].[this] [member] name]

Это то, что я пытаюсь вывести:

[dim[e]]nsion].[this]] [member]] name]

(обратите внимание на двойные квадратные скобки)

Как мне это сделать с помощью RegEx, используя .Net?

Еще примеры:

Input:  [dim[en]sion n[a]me ].[this [member] name]

Output: [dim[en]]sion n[a]]me ].[this [member]] name] 

Input:  [[dimension] name].[this member [name]]

Output: [[dimension]] name].[this member [name]]] 

person hopsusa    schedule 02.10.2012    source источник
comment
Regex не может обрабатывать такие сопоставления. У него нет никакого способа сослаться на внутреннюю часть. Вероятно, вы можете написать какое-нибудь сумасшедшее опережающее выражение, которое может сработать, но я настоятельно рекомендую использовать что-то более сложное, чем регулярные выражения.   -  person KRyan    schedule 02.10.2012
comment
Почему ] после побега this?   -  person Martin Ender    schedule 02.10.2012
comment
Не могли бы вы привести еще несколько примеров входных и выходных данных? Мне не совсем понятно, как могут быть отформатированы левая и правая стороны этого точечного символа...   -  person Andrew Kozak    schedule 03.10.2012
comment
Спецификация MDX указывает, что каждая правая квадратная скобка должна быть удвоена, чтобы ее можно было экранировать.   -  person hopsusa    schedule 03.10.2012
comment
В вашем первом и втором примере в конце нет дополнительной квадратной скобки, а в последнем примере она есть? Можете ли вы объяснить эту логику?   -  person Oliver    schedule 03.10.2012
comment
Regex не является правильным инструментом. Вы знаете, как отметить правильный ответ?   -  person paparazzo    schedule 03.10.2012
comment
Я прекрасно понимаю, что могу перебрать всю строку и заменить то, что нужно заменить. Я хотел бы использовать что-то более эффективное, чем это. Будет ли Linq предоставлять какую-либо функциональность, связанную с этой проблемой?   -  person hopsusa    schedule 03.10.2012
comment
См. мой ответ ниже для регулярного выражения, однако мне интересно узнать, будут ли у вас пробелы после закрытия ] когда-либо?   -  person Andrew Kozak    schedule 03.10.2012
comment
Почему вы полагаете, что зацикливание — не самый эффективный подход к этой проблеме? LINQ — это просто синтаксис, который перечисляет строку. Вы можете добраться туда с помощью Regex, но я серьезно сомневаюсь, что это будет быстрее, это простой анализ лайнера.   -  person paparazzo    schedule 03.10.2012


Ответы (2)


Зацикливание не требуется. Мы хотим сопоставить каждую правую скобку, кроме последней и той, которая непосредственно предшествует разделителю точка (.). Мы просто требуем, чтобы за нашей правой скобкой следовал один символ, и указываем, что это не должен быть символ точки. Я не уверен, как правильно это сказать в .NET, но вы хотите сопоставить ]([^\.]) и заменить на ]]$1, где $1 — это обратная ссылка на материал в круглых скобках в шаблоне соответствия. Если вы ожидаете пробела в конце вашего ввода (ов), я бы предложил сначала очистить его, так как это заменит последний ], если за ним следует пробел.

Вы можете протестировать здесь: http://www.regular-expressions.info/javascriptexample.html

EDIT 1: Проверено с помощью вышеуказанного тестера: http://imgur.com/a/VfR7W

EDIT 2: Проверено с помощью sed (необходимо для доступа к реальному компьютеру):

~ $ echo "                              
[dim[e]nsion].[this] [member] name]
[dim[en]sion n[a]me ].[this [member] name]
[[dimension] name].[this member [name]]
" > input.txt
~ $ cat input.txt

[dim[e]nsion].[this] [member] name]
[dim[en]sion n[a]me ].[this [member] name]
[[dimension] name].[this member [name]]

~ $ sed 's/]\([^\\.]\)/]]\1/g' input.txt

[dim[e]]nsion].[this]] [member]] name]
[dim[en]]sion n[a]]me ].[this [member]] name]
[[dimension]] name].[this member [name]]]

~ $ 

EDIT 3: В первоначальном ответе шаблон соответствия указан как ]([^\.]) с экранированной точкой (.), чтобы указать, что это буквальный символ точки. В зависимости от вашего языка вам может потребоваться экранировать другие символы в совпадении.

person Andrew Kozak    schedule 02.10.2012
comment
Эндрю, я проверил это, и ни один матч, похоже, не позаботился об этом. Можно предположить, что после закрывающей скобки пробела нет. - person hopsusa; 03.10.2012
comment
Извините, но регулярное выражение правильное. Я продемонстрировал это с помощью инструмента тестирования, указанного выше (regular-expressions.info), и загрузил результаты здесь: imgur.com /a/VfR7W Проблема, с которой вы столкнулись, вероятно, связана с экранированием или ошибкой синтаксиса. Не могли бы вы предоставить фактический код, который вы используете для выполнения этого поиска/замены? - person Andrew Kozak; 03.10.2012
comment
Андрей... это определенно решило проблему! Я действительно не думал, что это возможно. Цените свое время. - person hopsusa; 03.10.2012

Правила довольно просты: вставьте ] on ], но только если после [

string str = "[dim[e]nsion].[this] [member] name]";
char[] chars = str.ToArray();
StringBuilder sb = new StringBuilder();
bool leftLast = false;
foreach (char c in chars)
{
    sb.Append(c);
    if (c == '[')
    {
        leftLast = true;
    }
    else if (leftLast && c == ']')
    {
        sb.Append(']');
        leftLast = false;
    }
}
Debug.WriteLine(str);
Debug.WriteLine(sb.ToString());

Регулярное выражение найдет все ']', а затем применит ретроспективный анализ.
Этот цикл char[] устраняет ненужный обратный анализ.
Если lastLeft ложно, то нет причин даже сравнивать.

person paparazzo    schedule 02.10.2012