使用正则表达式返回字符串的前缀,其中剥离的字符串有时包含'/'

时间:2011-09-16 01:36:16

标签: ruby regex string

我正在尝试返回字符串的前缀,我的相关问题就在这里,但我遇到了一个新问题。

How to return the string prefix from regexp

基本上我有一个像

这样的字符串
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列表看起来像这样,并根据提供的示例数据进行更改,所以不幸的是,它并不像Mu的答案那么简单。

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 个答案:

答案 0 :(得分:3)

使第一个量词不成熟。

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

here on Regexr

?会使.*?尽可能少地匹配。

答案 1 :(得分:2)

您可以将负面观察混合到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

这只是算法的一个“脱离我的头脑”。