2015-07-15 2 views
2

Как получить подстроки между разделителями/несколькими разделителями? Например:Извлечь строку между разделителями

sample_string = "00990099" 
some_method(sample_string, "9") 
=> ["00"] 

sample_string = "00XXX00XX0X00X00" 
some_method(sample_string, "X") 
=> ["00", "0", "00"] 

Я пробовал использовать split, но есть ли для этого элегантное решение?

ответ

5

Вам нужно lookaround регулярное выражение для этого, как это:

(?<=X)[^X]+(?=X) 

RegEx Demo

В Ruby вы можете использовать string.scan(regex), чтобы получить все матчи

+0

Это неверно для второй тестовой строки в вашей демонстрационной ссылке. –

+0

Правило Regex верное. Это связано с несколькими линиями в демо. [См. Здесь снова с таким же регулярным выражением] (http://rubular.com/r/meeO45qVyj) – anubhava

+0

hmm. Еще одна проблема. –

0

Я думаю, что это довольно элегантна:

str.split(delim, -1)[1...-1].reject(&:empty?) 

В отличие от ответа анубхавы в этот канун n работает с многосимвольными разделителями. Аргумент -1 для split останавливает его от подавления конечных нулевых полей, что необходимо, так как вам нужно знать, заканчивается ли строка с разделителем или нет.

class String 
    def split_delim delim 
    split(delim, -1)[1...-1].reject(&:empty?) 
    end 
end 

"00XXX00XX0X00X00".split_delim "X" 
# ["00", "0", "00"] 

"splitting this long string is my mission".split_delim "is" 
# [" long string ", " my m"] 
+0

[Для многосимвольного разделителя используйте это] (http://rubular.com/r/dKT0MIOo8E) – anubhava

+0

Нет. См. Этот пример: http://rubular.com/r/SUZj8hobYa – Max

+0

Что в этом плохого? Если у вас есть разделитель как 'XX', то третий элемент' X' будет частью совпадения. – anubhava

0

Несколько других способов:

1: Обрезка строки и использовать String#scan

def some_method(str, c) 
    str.gsub(/^[^#{c}]+|[^#{c}]+$/,"").scan /[^#{c}]+/ 
end 

some_method("00990099", "9")   #=> ["00"] 
some_method("00XXX00XX0X00X00", "X") #=> ["00", "0", "00"] 
some_method("0000", "9")    #=> [] 
some_method("9999", "9")    #=> [] 

2: Разделение на группы и использовать Enumerable#each_cons

def some_method(str, c) 
    str.gsub(r) split(/(#{c}+)/) 
    .each_cons(3) 
    .with_object([]) { |(_,s,_),a| a << s unless s =~ /#{c}/ } 
end 

some_method("00990099", "9")   #=> ["00"] 
some_method("00XXX00XX0X00X00", "X") #=> ["00", "0", "00"] 
some_method("0000", "9")    #=> [] 
some_method("9999", "9")    #=> [] 

Обратите внимание, что при использовании, #{c}+ в регулярном выражении должно быть в группе захвата, чтобы сохранить группы c, с помощью которых разбивается str.

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