Возвратите префикс строки, используя регулярное выражение, где разделенная строка иногда содержит '/' - PullRequest
2 голосов
/ 16 сентября 2011

Я пытаюсь вернуть префикс строки, мой связанный с этим вопрос здесь, но я столкнулся с новой проблемой.

Как вернуть префикс строки из регулярного выражения

По сути, у меня есть строки вроде

23430-BL
23430BZ
23430BK/BL

Расширения, которые я пытаюсь удалить:

strip_ext = BK/BL|BZ|BL

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

prefix = sample_data[/(.*[^-])-?(?:#{strip_ext})/,1]

Это возвращает

23430
23430
23430-BK

Теоретически я понимаючто регулярное выражение находит совпадение BL и по какой-то причине выбирает его как совпадение с BK / BL.Но есть ли способ получить регулярное выражение, чтобы найти BK / BL, а не BL?

К сожалению, перед той частью, которую я хочу раздеть, не всегда есть тире.

Я добавил оригинальный список strip_ext в качестве примера и подумал, что это облегчит его понимание.Фактический список strip_ext выглядит следующим образом и изменяется в зависимости от предоставленных образцов данных, поэтому, к сожалению, это не так просто, как ответ Му ниже.

AM/DB|AM/BN|RD/BK|PR/WT|YP/BN|YP/CH|YP/DB|PK/BN|PK/CH|PK/DB|SF/BN|SF/CH|SF/DB|AM/CH|BN/CH|BN/DB|CH/BN|CH/DB|DB/BN|DB/CH|BN/BN|CH/CH|MR/BN|MR/CH|MR/DB|DB/DB|AM/AB|DIC/BN|DIC/CH|DIC/DB|BN|DB|WT|BN/WT|BK|WT/BN|BK/BN|BK/DB|BL/BN|BL/DB|BK/CH|BL/CH|AM|CH|FR|SB|AM/BK|AM/WT|PT/CH|BG/CH|BG/DB|MF/CH|MF/DB|YR/CH|YR/DB|WT/DB|pt/bn

Ответы [ 2 ]

3 голосов
/ 16 сентября 2011

Сделать первый квантификатор несвязным.

(.*?[^-])-?(?:BK/BL|BZ|BL)

См. здесь на Regexr

? заставляет .*? совпадать как можно меньше.

2 голосов
/ 16 сентября 2011

Вы можете смешать отрицательный взгляд в свой BL матчер:

/(.*[^-])-?(?:BK\/BL|BZ|(?<!BK\/)BL)/

Добавление (?<!BK\/) означает, что вы хотите сопоставить BL, за исключением случаев, когда ему предшествует BK/.

Быстрый тест:

>> %w{23430-BL 23430GR 23430BK/BL}.map { |s| s[/(.*[^-])-?(?:BK\/BL|BZ|(?<!BK\/)BL)/,1] }
=> ["23430", nil, "23430"]

Ваш пример выходных данных не совпадает с вашим входом, является ли "GR" опечаткой в ​​ваших входах или "BZ" опечаткой в ​​вашем регулярном выражении?


Учитывая, что ваши шаблоны не являются фиксированными, вы можете полностью обойти регулярные выражения и вернуться к простой обработке строк. Вот лучший пример того, что я упомянул в своем комментарии:

require 'set'

# The suffix list that you get from somewhere.
suffixes  = [ 'BK/BL', 'BZ', 'BL' ]

# We want to do a couple things at once here. For each suffix, we
# want both the suffix and the suffix with a leading '-' attached,
# the `map` and `flatten` stuff does that. Then we group them by
# length to get a hash like:
#
#     { 2 => ['BZ','BL'], 3 => ['-BZ', '-BL'], 5 => ['BK/BL'], ... }
#
by_length = suffixes.map { |suffix| [suffix, '-' + suffix ] }.flatten.group_by(&:length)

# Now we reorganize our suffixes into sets with the set of longest
# suffixes first and the set of shortest suffixes last. The result
# will be:
#
#     [#<Set: {"-BK/BL"}>, #<Set: {"BK/BL"}>, #<Set: {"-BZ", "-BL"}>, #<Set: {"BZ", "BL"}>]
#
sets = by_length.keys.sort { |a,b| b <=> a }.map { |k| Set.new(by_length[k]) }

# Then we can just spin through sets, pull off the suffix of the
# appropriate length from the string, and see if it is in our set.
# If it is then chop the suffix off the string, do whatever is to be
# done with chopped string, and break out for the next string.
#
%w{ 23430-BL 23430BZ 23430BK/BL }.each do |string|
    sets.each do |suffixes|
        len = suffixes.first.length
        sfx = string[string.length - len, len]
        if(suffixes.include?(sfx))
            puts string[0 .. -(len + 1)]
            break
        end
    end
end

Это просто иллюстрация алгоритма "с головы до головы".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...