Как мне сопоставить часть строки, только если ей не предшествуют определенные символы? - PullRequest
4 голосов
/ 16 октября 2008

Я создал следующий шаблон регулярных выражений, пытаясь сопоставить строку длиной 6 символов, заканчивающуюся либо "PRI", либо "SEC", если только строка = "SIGSEC". Например, я хочу сопоставить ABCPRI, XYZPRI, ABCSEC и XYZSEC, но не SIGSEC.

(\w{3}PRI$|[^SIG].*SEC$)

Это очень близко и что-то вроде работ (если я передаю "SINSEC", он возвращает частичное совпадение с "NSEC"), но у меня нет хорошего представления об этом в его текущей форме. Кроме того, у меня может возникнуть необходимость добавить больше исключений, кроме «SIG», позже и понять, что это, вероятно, не слишком хорошо масштабируется. Есть идеи?

Кстати, я использую System.Text.RegularExpressions.Regex.Match () в C #

Спасибо, Рич

Ответы [ 8 ]

6 голосов
/ 16 октября 2008

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

((?!SIGSEC)\w{3}(?:SEC|PRI))

Редактировать: Комментатор указал, что .NET поддерживает отрицательные взгляды, поэтому это должно работать нормально (спасибо, Чарли).

2 голосов
/ 16 октября 2008

Чтобы помочь разобрать ответ Дана (правильный), вот как это работает:

(           // outer capturing group to bind everything
 (?!SIGSEC) // negative lookahead: a match only works if "SIGSEC" does not appear next
 \w{3}      // exactly three "word" characters
 (?:        // non-capturing group - we don't care which of the following things matched
   SEC|PRI  // either "SEC" or "PRI"
 )
)

Все вместе: ((?! SIGSEC) \ w {3} (?: SEC | PRI))

1 голос
/ 16 октября 2008

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

private Boolean HasValidEnding(String input)
{
    if (input.EndsWith("SEC",StringComparison.Ordinal) || input.EndsWith("PRI",StringComparison.Ordinal))
    {
        if (!input.Equals("SIGSEC",StringComparison.Ordinal))
        {
            return true;
        }
    }
    return false;
}

или в одну строку

private Boolean HasValidEnding(String input)
{
    return (input.EndsWith("SEC",StringComparison.Ordinal) || input.EndsWith("PRI",StringComparison.Ordinal)) && !input.Equals("SIGSEC",StringComparison.Ordinal);
}

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

1 голос
/ 16 октября 2008

Вы можете попробовать это:

@"\w{3}(?:PRI|(?<!SIG)SEC)"
  • Соответствует 3 символам "слова"
  • Соответствует PRI или SEC (но не после SIG, т. Е. SIGSEC исключен) (? <! X) y - отрицательный взгляд назад (он объединяет y, если перед ним нет x) </li>

Кроме того, мне может понадобиться добавить еще исключения, кроме "SIG" позже и понять, что это, вероятно, не будет масштабироваться слишком хорошо

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

@"\w{3}(?:PRI|(?<!SIG|FOO)SEC)"
0 голосов
/ 16 октября 2008

Пойдите и получите Regexbuddy от RegExBuddy.com - это удивительно простой инструмент, который поможет вам легко разобраться в самом сложном регулярном выражении.

0 голосов
/ 16 октября 2008

Возможно, вы даже не захотите делать исключения в регулярном выражении. Например, если бы это был Perl (я не знаю C #, но вы, вероятно, можете следовать за ним), я бы сделал это так

if ( ( $str =~ /^\w{3}(?:PRI|SEC)$/ ) && ( $str ne 'SIGSEC' ) )

должно быть ясно. Он делает именно то, что вы хотели:

  • Три слова, за которыми следуют PRI или SEC и
  • Это не SIGSEC

Никто не говорит, что вы должны заставить все в одно регулярное выражение.

0 голосов
/ 16 октября 2008

«Некоторые люди, сталкиваясь с проблемой, думают:« Я знаю, я буду использовать регулярные выражения ». Теперь у них две проблемы ". Джейми Завински

0 голосов
/ 16 октября 2008

Лично я был бы склонен создать список исключений, используя вторую переменную, а затем включить его в полное выражение - это подход, который я использовал в прошлом, когда нужно было построить любой * 1002. * сложное выражение.

Что-то вроде exclude = 'someexpression'; prefix = 'list of prefixes'; suffix = 'list of suffixes'; expression = '{prefix}{exclude}{suffix}';

...