Ответ 1
Но тогда просто
ends = '20080201..20080229'.split('..').map{|d| Integer(d)}
ends[0]..ends[1]
В любом случае я не рекомендую eval по соображениям безопасности
У меня есть код Ruby, который принимает даты в командной строке в формате:
-d 20080101,20080201..20080229,20080301
Это означает, что я хочу запускать для всех дат между 20080201 и 20080229 (включительно) и другими датами, представленными в списке.
Учитывая, что я могу получить строку 20080201..20080229, что лучший способ преобразовать ее в экземпляр Range. В настоящее время я использую eval, но похоже, что должен быть лучший способ.
@Purfideas Я искал более общий ответ для преобразования любой строки типа int..int в диапазон, который я предполагаю.
Но тогда просто
ends = '20080201..20080229'.split('..').map{|d| Integer(d)}
ends[0]..ends[1]
В любом случае я не рекомендую eval по соображениям безопасности
Range.new(*self.split("..").map(&:to_i))
Вложение без аргументов хорошо работает для двух массивов элементов:
rng='20080201..20080229'.split('..').inject { |s,e| s.to_i..e.to_i }
Конечно, это можно сделать общим
class Range
def self.from_ary(a)
a.inject{|s,e| s..e }
end
end
rng = Range.from_ary('20080201..20080229'.split('..').map{|s| s.to_i})
rng.class # => Range
Предполагая, что вы хотите, чтобы диапазон правильно повторялся через месяцы и т.д., попробуйте
require 'date'
ends = '20080201..20080229'.split('..').map{|d| Date.parse(d)}
(ends[0]..ends[1]).each do |d|
p d.day
end
Для этого здесь есть драгоценный камень. Использует регулярное выражение для проверки строки (без страха от SQL-инъекции), а затем eval.
Объединяя ответ @Purfideas с другим ответом где-то в StackOverflow, я решил это, также окружая код проверкой ввода, поэтому единственное, что используется, - допустимый перечислимый
if !value[/^[0-9]+\.\.[0-9]+$/].nil?
ends = value.split('..').map{|d| Integer(d)}
value = ends[0]..ends[1]
end
Он по существу переписывает ваше строковое значение перечислимому значению. Это пригодится, если вы добавите перечислимое поле в конфигурационный файл yaml.
Если вам это нужно для вашего приложения, вы можете расширить регулярное выражение с помощью дополнительной третьей литеральной точки, которая может быть необязательной.
Если мы сделаем это как
v= "20140101..20150101"
raise "Error: invalid format: #{v}" if /\d{8}\.\.\d{8}/ !~ v
r= eval(v)
и злоумышленник имеет способ обойти проверку рейза (просто используя управление временем выполнения, чтобы отключить исключения), тогда мы можем получить опасную оценку, которая потенциально может уничтожить юниверс.
Итак, ради сокращения векторов атак мы проверяем формат, а затем выполняем разбор вручную, а затем проверяем результаты
v= "20140101..20150101"
raise "Error: invalid format: #{v}" if /\d{8}\.\.\d{8}/ !~ v
r= Range.new(*v.split(/\.\./).map(&:to_i))
raise "Error: invalid range: #{v}" if r.first> r.last
Здесь предположим, что вы хотите сохранить хеш как системное постоянное значение и извлечь его в любую модель. Хеш-клавиша будет значением диапазона.
hash_1 = {1..5 => 'a', 6..12 => 'b', 13..67 => 'c', 68..9999999 => 'd'}
Затем создайте системную константу со значением как hash_1.to_json. .to_json преобразует ваш объект хэша в объект JSON. Теперь внутри кода создайте новый хэш hash_2,
JSON.parse(SystemConstant.get('Constant_name')).each{|key,val| temp_k=key.split('..').map{|d| Integer(d)}; hash_2[temp_k[0]..temp_k[1]] = val}
Новый hash_2 будет обязательным hash_1