2010-11-02 3 views
5

Мне нужно регулярное выражение, которое должно использоваться для замены текста. Пример: текст, который нужно сопоставить, - ABC (который может быть окружен квадратными скобками), текст подстановки - DEF. Это достаточно основательно. Усложнение состоит в том, что I не хотят сопоставлять текст ABC, когда ему предшествует шаблон \[[\d ]+\]\. - другими словами, когда ему предшествует слово или набор слов в скобках, за которым следует период.RegEx для соответствия шаблону, если ему не предшествует другой шаблон

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

1. [xxx xxx].[ABC] > [xxx xxx].[ABC] (does not match - first part fits the pattern) 
2. [xxx xxx].ABC > [xxx xxx].ABC (does not match - first part fits the pattern) 
3. [xxx.ABC  > [xxx.DEF  (matches - first part has no closing bracket) 
4. [ABC]   > [DEF]   (matches - no first part) 
5. ABC    > DEF    (matches - no first part) 
6. [xxx][ABC]  > [xxx][DEF]  (matches - no period in between) 
7. [xxx]. [ABC] > [xxx] [DEF]  (matches - space in between) 

Что это сводится к тому, что: как я могу указать предыдущий образец, когда настоящее, как описано будет предотвратить матч? Каким будет шаблон в этом случае? (C# аромат регулярного выражения)

+0

Я изменил 'DEF' в вашей второй«после»строки в' ABC 'чтобы указать, что никакой замены не произошло. Это вы имели в виду, не так ли? –

+0

Да. Просто убедитесь, что вы обращали внимание. –

ответ

11

Вы хотите негативное выражение внешнего вида. Они выглядят как (?<!pattern), так:

(?<!\[[\d ]+\]\.)\[?ABC\]? 

Обратите внимание, что это не принуждать подходящую пару квадратных скобок ABC; он просто позволяет использовать опциональный открытый кронштейн до и после этого закрывать скобы. Если вы хотите, чтобы заставить соответствующие пары или ничего, вы должны использовать чередование:

(?<!\[[\d ]+\]\.)(?:ABC|\[ABC\]) 

Это использует не захватывая круглые скобки, чтобы разграничить чередование. Если вы хотите захватить ABC, вы можете превратить это в группу захвата.

ETA: Причина, по которой первое выражение, похоже, терпит неудачу, заключается в том, что оно соответствует ABC], которому не предшествует запрещенный текст. Открытая скобка [ не является обязательной, поэтому она просто не соответствует этому. Обойти это переложить дополнительный открытый кронштейн [ в отрицательный взгляд, за утверждение, например, так:

(?<!\[[\d ]+\]\.\[?)ABC\]? 

пример того, что он соответствует и не делает:

[123].[ABC]: fail (expected: fail) 
[123 456].[ABC]: fail (expected: fail) 
[123.ABC: match (expected: match) 
    matched: ABC 
ABC: match (expected: match) 
    matched: ABC 
[ABC]: match (expected: match) 
    matched: ABC] 
[ABC[: match (expected: fail) 
    matched: ABC 

Попытка сделать наличие открытой скобки [ силы комбинационной близко кронштейн ], как задумано второй шаблон, сложнее, но это похоже на работу:

(?:(?<!\[[\d ]+\]\.\[)ABC\]|(?<!\[[\d ]+\]\.)(?<!\[)ABC(?!\])) 

Пример того, что он соответствует и не делает:

[123].[ABC]: fail (expected: fail) 
[123 456].[ABC]: fail (expected: fail) 
[123.ABC: match (expected: match) 
    matched: ABC 
ABC: match (expected: match) 
    matched: ABC 
[ABC]: match (expected: match) 
    matched: ABC] 
[ABC[: fail (expected: fail) 

примеры были созданы с помощью этого кода:

// Compile and run with: mcs so_regex.cs && mono so_regex.exe 
using System; 
using System.Text.RegularExpressions; 

public class SORegex { 
    public static void Main() { 
    string[] values = {"[123].[ABC]", "[123 456].[ABC]", "[123.ABC", "ABC", "[ABC]", "[ABC["}; 
    string[] expected = {"fail", "fail", "match", "match", "match", "fail"}; 
    string pattern = @"(?<!\[[\d ]+\]\.\[?)ABC\]?"; // Don't force [ to match ]. 
    //string pattern = @"(?:(?<!\[[\d ]+\]\.\[)ABC\]|(?<!\[[\d ]+\]\.)(?<!\[)ABC(?!\]))"; // Force balanced brackets. 
    Console.WriteLine("pattern: {0}", pattern); 
    int i = 0; 
    foreach (string text in values) { 
     Match m = Regex.Match(text, pattern); 
     bool isMatch = m.Success; 
     Console.WriteLine("{0}: {1} (expected: {2})", text, isMatch? "match" : "fail", expected[i++]); 
     if (isMatch) Console.WriteLine("\tmatched: {0}", m.Value); 
    } 
    } 
} 
+0

Эти классы персонажей выглядят не совсем корректно. Что такое скрытая скобка? И разве этот внешний вид с переменной длиной? – tchrist

+2

@tchrist: аромат регулярного выражения .NET действительно поддерживает неограниченные, с переменной длиной lookbehinds. Что касается этой невыпадающей квадратной скобки, он, похоже, скопировал ошибку из регулярного выражения OP; это происходит много. –

+0

@ Алан, это действительно здорово! Благодаря!! – tchrist

Смежные вопросы