2015-02-19 5 views
0

Так что я сейчас пытаюсь сортировать значения из файла. Я застрял в поиске первого атрибута и не знаю, почему. Я новичок в регулярном выражении и рубине, поэтому не знаю, как решить проблему. Я пытаюсь найти значения a, b, c, d, e, где они все положительные числа.Использование регулярных выражений регулярных выражений и рубинов для нахождения значений

Вот что линия будет выглядеть

length=<a> begin=(<b>,<c>) end=(<d>,<e>) 

Вот что я использую, чтобы найти значение

current_line = file.gets 
if current_line == nil then return end 
while current_line = file.gets do 
    if line =~ /length=<(\d+)> begin=((\d+),(\d+)) end=((\d+),(\d+))/ 
     length, begin_x, begin_y, end_x, end_y = $1, $2, $3, $4, $5 
     puts("length:" + length.to_s + " begin:" + begin_x.to_s + "," + begin_y.to_s + " end:" + end_x.to_s + "," + end_y.to_s) 
    end 
end 

по какой-то причине он не печатает что-нибудь, так что я предполагаю, что это никогда не находит совпадение

ввода образца длина = 4 = начать (0,0) = конец (3,0)


Линия с 0-4 знаками после 2 целых чисел, разделенных запятыми. Так это может быть любой из них:

2 4 1.3434324,3.543243,4.525324 
1 2  
18 3.3213,9.3233,1.12231,2.5435  
7 9 2.2,1.899990  
0 3 2.323  
+0

@Jake Старший, я отправил ответ, делает то, что вы хотите. – 7stud

ответ

2

Вот ваш регулярное выражение:

r = /length=<(\d+)> begin=((\d+),(\d+)) end=((\d+),(\d+))/ 
str.scan(r) 
    #=> nil 

Во-первых, нам нужно, чтобы избежать скобку:

r = /length=<(\d+)> begin=\((\d+),(\d+)\) end=\((\d+),(\d+)\)/ 

Далее, добавить недостающее < и > после "begin" и "end".

r = /length=<(\d+)> begin=\(<(\d+)>,<(\d+)>\) end=\(<(\d+)>,<(\d+)>\)/ 

Теперь давайте попробуем:

str = "length=<4779> begin=(<21>,<47>) end=(<356>,<17>)" 

, но сначала давайте set the mood

str.scan(r) 
    #=> [["4779", "21", "47", "356", "17"]] 

успеха!

Наконец (хотя, вероятно, не нужно), мы могли бы заменить одиночные пробелы с \s+, что позволяет один или несколько пробелов:

r = /length=<(\d+)>\s+begin=\(<(\d+)>,<(\d+)>\)\send=\(<(\d+)>,<(\d+)>\)/ 

Добавление

ОП спросил, как это было бы изменить, если некоторые из числовых значений были float. Я не понимаю точно, что было запрошено, но при необходимости может быть изменено следующее. Я предположил, что все числа неотрицательны. Я также проиллюстрировал один способ «создать» регулярное выражение, используя Regexp#new.

s1 = '<(\d+(?:\.\d+)?)>' # note single parens 
    #=> "<(\\d+(?:\\.\\d+)?)>" 
    s2 = "=\\(#{s1},#{s1}\\)" 
    #=> "=\\(<(\\d+(?:\\.\\d+)?)>,<(\\d+(?:\\.\\d+)?)>\\)" 
    r = Regexp.new("length=#{s1} begin#{s2} end#{s2}") 
    #=> /length=<(\d+(?:\.\d+)?)> begin=\(<(\d+(?:\.\d+)?)>,<(\d+(?:\.\d+)?)>\) end=\(<(\d+(?:\.\d+)?)>,<(\d+(?:\.\d+)?)>\)/ 

    str = "length=<47.79> begin=(<21>,<4.7>) end=(<0.356>,<17.999>)" 

    str.scan(r) 
    #=> [["47.79", "21", "4.7", "0.356", "17.999"]] 
+0

для чего? и вам нужно иметь \\ (и \\) всякий раз, когда вы используете круглые скобки в регулярном выражении? любое объяснение будет большим –

+0

'\ b' является (нулевой шириной) словом. Он предотвращает совпадение, скажем, '' oddlength ''. (Возможно, не обязательно). Некоторые символы, включая круглые скобки, означают что-то в регулярных выражениях ('(..)' - группа захвата, '(?: ...)' - группа без захвата и т. Д.), Поэтому они должны быть экранированы, чтобы сообщить синтаксическому анализатору что вы просто ссылаетесь на этого персонажа. Однако это немного сложно, так как большинство этих символов не нужно экранировать, когда внутри класса символов (например, '[() abc]'). –

+0

Извините, я нашел свое решение. Однако я просто добавил редактирование для своего OP. Так или иначе, вы могли бы объяснить мне, как я могу найти этот формат? Я пробовал использовать (\ w), но запятые отбросить его –

0

ввода пробы:

length=4 begin=(0,0) end=(3,0) 

данных.ТХТ:

length=3 begin=(0,0) end=(3,0) 
length=4 begin=(0,1) end=(0,5) 
length=2 begin=(1,3) end=(1,5) 

Попробуйте это:

require 'pp' 

Line = Struct.new(
    :length, 
    :begin_x, 
    :begin_y, 
    :end_x, 
    :end_y, 
) 

lines = [] 

IO.foreach('data.txt') do |line| 
    numbers = [] 

    line.scan(/\d+/) do |match| 
    numbers << match.to_i 
    end 

    lines << Line.new(*numbers) 
end 

pp lines 

puts lines[-1].begin_x 

--output:-- 
[#<struct Line length=3, begin_x=0, begin_y=0, end_x=3, end_y=0>, 
#<struct Line length=4, begin_x=0, begin_y=1, end_x=0, end_y=5>, 
#<struct Line length=2, begin_x=1, begin_y=3, end_x=1, end_y=5>] 
1 

С этим data.txt:

2 4 1.3434324,3.543243,4.525324 
1 2  
18 3.3213,9.3233,1.12231,2.5435  
7 9 2.2,1.899990  
0 3 2.323  

Попробуйте это:

require 'pp' 

data = [] 

IO.foreach('data.txt') do |line| 
    pieces = line.split 
    csv_numbers = pieces[-1] 

    next if not csv_numbers.index('.') #skip the case where there are no floats on a line 

    floats = csv_numbers.split(',') 
    data << floats.map(&:to_f) 
end 

pp data 

--output:-- 
[[1.3434324, 3.543243, 4.525324], 
[3.3213, 9.3233, 1.12231, 2.5435], 
[2.2, 1.89999], 
[2.323]] 
Смежные вопросы