2010-11-02 3 views
0

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

Я хочу, чтобы регулярное выражение для моей программы Ruby, чтобы соответствовать слово с ниже рисунком

шаблон имеет

  1. Список букв (например. ЦКА => 1 А, 1 в, 2 С)
  2. N Wild Card Charaters (N может быть равно 0 или 1, или 2)
  3. фиксированного слова (например, « XY») ,

Правила:

  1. Что касается Списка писем, он должен соответствовать слова с

    а. 0 или 1 A

    b. 0 или 1 B

    c. 0 или 1 или 2 C

  2. Основываясь на значении N, может быть 0 или 1 или 2 диких символа
  3. Исправленное слово всегда в том порядке, в котором оно задано.
  4. Сочетание все это может быть в любом порядке и должны соответствовать такие слова, как ниже

ABWXY (если дикий полукокса = 1)

BAXY

CXYCB

Но не слова с 2 A или 2 B

Я использую шаблон, подобный^[ABCC] *. XY $

Но он ищет слова с более чем 1 A или 1 B или 2 C, а также ищет слова, которые заканчиваются XY, я хочу, чтобы все слова, которые имеют XY в любом месте, буквы и дикие символы в любом положении.

ответ

1

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

Просто, чтобы привести пример вашей проблемы, регулярное выражение, подобное/[abc] /, будет соответствовать каждому вхождению a, b и c независимо от того, сколько раз эти буквы появляются в строке. Вы можете попробовать/c {1,2} /, и он будет соответствовать «c», «cc» и «ccc». Он соответствует последнему случаю, потому что у вас есть шаблон 1 c и 2 c в «ccc».

Одна вещь, которую я нашел бесценной при разработке и отладке регулярных выражений, - rubular.com. Попробуйте несколько примеров, и я думаю, вы увидите, с чем вы столкнулись.

Я не знаю, действительно ли это поможет, но это может помочь вам выбрать направление.

1

Вам необходимо правильно разобрать шаблон. В регулярных выражениях [ABCC] означает «любой из A, B или C», где дубликат C игнорируется. Это оператор набора, а не оператор группировки, такой как ().

Что вы, кажется, описываете, это создание регулярного выражения на основе параметров. Вы можете сделать это, передав строку Regexp.new и используя результат.

Пример примерно:

def match_for_options(options) 
    pattern = '^' 

    pattern << 'A' * options[:a] if (options[:a]) 
    pattern << 'B' * options[:b] if (options[:b]) 
    pattern << 'C' * options[:c] if (options[:c]) 

    Regexp.new(pattern) 

конец

Вы бы использовать это что-то вроде этого:

if (match_for_options(:a => 1, :c => 2).match('ACC')) 
    # ... 
end 
+0

а, в, с, с, дикий. -char, (XY). В любом порядке и в любой позиции. Упомянутый шаблон будет соответствовать ACC, но не r CAC или CA. Как сказать, чтобы искать буквы и дикие символы во всех комбинациях? –

+0

Регулярные выражения иногда являются сложными вещами для правильной разработки, поэтому хорошая ссылка на различные инструменты в вашем распоряжении внутри системы - хорошая идея. [Rubular] (http://rubular.com/) - отличное место для экспериментов с потенциальными выражениями, но для получения желаемого шаблона может потребоваться некоторое время. Иногда решение не является регулярным выражением, а токенизатором или парсером, который является намного более надежным. Я все еще не уверен, какие шаблоны вы хотите описать, так что вышеприведенный код является всего лишь примером одного метода. – tadman

1

Поскольку вы хотите, чтобы эти «элементы» отображались в любом порядке, вам может быть лучше написать немного кода Ruby, который проходит через строку от начала до конца и подсчитывает количество символов As, Bs и Cs , находит, содержит ли она вашу нужную подстроку. Если число As, Bs и Cs находится в ваших желаемых пределах и содержит нужную подстроку, а ее длина (то есть количество символов) равна длине нужной подстроки, плюс # из As, плюс # of Bs, плюс # of Cs, плюс не более N символов больше, чем это, тогда строка хороша, в противном случае это плохо. Собственно, чтобы быть осторожным, сначала нужно найти нужную подстроку, а затем удалите из исходной строки, затем подсчитайте № из As, Bs и Cs, потому что в противном случае вы можете непреднамеренно подсчитать As, Bs и Cs, которые отображаются в нужной строке, если они есть.

Вы можете делать то, что хотите, с регулярным выражением, но это будет длинное уродливое регулярное выражение. Зачем? Потому что вам понадобится отдельный «случай» в регулярном выражении для каждого из возможных порядков элементов. Например, регулярное выражение «^ ABC..XY $» будет соответствовать любой строке, начинающейся с «ABC» и заканчивающейся «XY» и имеющей два символа wild card в середине. Но только в таком порядке. Если вы хотите регулярное выражение для всех возможных заказов, вам нужно будет перечислить все эти заказы в регулярном выражении, например. он начнет что-то вроде «^ (ABC..XY | ACB..XY | BAC..XY | BCA..XY |» и продолжим оттуда, причем около 5! = 120 разных заказов для этого списка из 5 элементов, то вам понадобится больше для случаев, когда не было A, затем больше для случаев, когда не было B и т. д. Я думаю, что регулярное выражение является неправильным инструментом для работы здесь.

2

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

if subject =~ 
    /^       # start of string 
    (?!(?:[^A]*A){2})   # assert that there are less than two As 
    (?!(?:[^B]*B){2})   # and less than two Bs 
    (?!(?:[^C]*C){3})   # and less than three Cs 
    (?!(?:[ABCXY]*[^ABCXY]){3}) # and less than three non-ABCXY characters 
    (?=.*XY)     # and that XY is contained in the string. 
    /x 

    # Successful match 
else 
    # Match attempt failed 
end 

Это предполагает, что ни один из символов A, B, C, X или Y не допускаются как подстановочные знаки

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