Поискав в интернете способ распарсивания командной строки, решил таки пополнить список самодельщиков и любителей парсеров. Возможно кому-нибудь пригодится данный код.
Итак, задача стояла следующая: необходимо распарсить набор параметров адресной строки URL, с возможностью получать массивы. Поискав в интернете решение этой задачи, решил, что будет быстрее сделать самому то, что нужно.
def params_to_hash(_params="")
return {} if _params.grep(/\=/).blank?
result = {}
_params = (URI.parse(_params).query || "") unless _params.grep(/\?/).blank?
l = lambda {|x, a| a[0]=="" ? (a[1].is_a?(Array) ? (x = x || []) << l.call(x, a[1]) : CGI.unescape(a[1])) : (x = x || {}).merge({a[0].to_sym => a[1].is_a?(Array) ? l.call(x[a[0].to_sym], a[1]) : CGI.unescape(a[1])}) }
_params.split("&").each do |item|
next if item.size == 0
item += " " if item.split(/\=/).size < 2
k = item.split(/\]\[|\[|\]|\=/).reverse
k[0] = "" if k[0] == " "
q = k.inject(nil) {|r, i| r = (r.nil? ? i : [i, r]) }
result = l.call(result, q)
end
return result
end Основную итерацию разборки параметра можно поделить условно на две части.
Подготовка строки параметра для рекурсивной обработки. Например, параметр вида «g[b][e][]=2» преобразуется в массив основным свойством которого является вложенность массивов размерность которых не превышает два элемента «[»g«, [»b«, [»e«, [»«, [»«, „2“]]]]]». Пустые строки в данном наборе расцениваются как признак массива «[]» и знак равно «=».
Пример подготовки массива для параметра с конечным значением типа массив «[]»
>> k = "g[b][e][]=2".split(/\]\[|\[|\]|\=/).reverse
=> ["2", "", "", "e", "b", "g"]
>> q = k.inject(nil) {|r, i| r = (r.nil? ? i : [i, r]) }
=> ["g", ["b", ["e", ["", ["", "2"]]]]] Пример подготовки массива для параметра с конечным значением типа строка или число «…»
>> k = "g[b][e]=2".split(/\]\[|\[|\]|\=/).reverse
=> ["2", "", "e", "b", "g"]
>> q = k.inject(nil) {|r, i| r = (r.nil? ? i : [i, r]) }
=> ["g", ["b", ["e", ["", "2"]]]] Последующая обработка массива выполняется рекуррентной лямбда-функцией. В качестве параметров эта функция принимает частично заполненный хэш параметров и массив. Лямбда функция дополняет или создает заново во входном хэше параметр на основе цепочки заложенной в массиве. Полагаю, глядя на массив, несложно будет понять, как работает лямбда функция.
Данная функция парсирует параметры вида «g[b][e][]=1&g[b][e][]=2&g[b][e][]=34&g[b][c]=d», но, увы, она не расчитана для парсирования массива сложных объектов, например, «g[][b][e][]=expression». Массив для этой функции может быть только конечным значением.
Пример работы функции
>> h = "g[b][e][]=1&g[b][e][]=2&g[b][e][]=34&g[b][c]=d"
=> "g[b][e][]=1&g[b][e][]=2&g[b][e][]=34&g[b][c]=d"
>> params_to_hash(h)
=> {:g=>{:b=>{:c=>"d", :e=>["1", "2", "34"]}}} Любителям dry-кода предлагаю вносить поправки 🙂








