Как разделить текст на пары ключ-значение? - PullRequest
3 голосов
/ 18 января 2012

Я создаю скрипт для чтения и разбора файлов уценки в Ruby.Сценарий должен иметь возможность считывать и понимать информацию заголовка multimarkdown в верхней части файлов, чтобы он мог выполнять дополнительные действия над выводом.

Значения заголовка выглядят так:

Title: My Treatise on Kumquats
Author: Joe Schmoe
Author URL: http://somedudeswebsite.me/
Host URL: http://googlesnewthing.com/
Created: 2012-01-01 09:41

Я не могу понять, как разбить строки текста в простой словарь значений ключей.Кажется, встроенная функция разделения не работает в этом случае, потому что я хочу, чтобы она разделялась только при первом появлении двоеточия (:) в каждой строке.Дополнительные двоеточия будут частью строки значения.

В случае, если это имеет значение, я использую Ruby 1.8.7 на OS X.

Ответы [ 5 ]

7 голосов
/ 18 января 2012

Это делает это:

s = <<EOS
Title: My Treatise on Kumquats
Author: Joe Schmoe
Author URL: http://somedudeswebsite.me/
Host URL: http://googlesnewthing.com/
Created: 2012-01-01 09:41
EOS

h = Hash[s.each_line.map { |l| l.chomp.split(': ', 2) }]
p h

Выход:

{"Title"=>"My Treatise on Kumquats", "Author"=>"Joe Schmoe", "Author URL"=>"http://somedudeswebsite.me/", "Host URL"=>"http://googlesnewthing.com/", "Created"=>"2012-01-01 09:41"}
6 голосов
/ 18 января 2012

Используйте split с необязательным вторым параметром (спасибо @MichaelKohl)

s = 'Author URL: http://somedudeswebsite.me/'
key, value = s.split ': ', 2
puts key
puts value

Выход

Author URL
http://somedudeswebsite.me/
1 голос
/ 18 января 2012

Вы можете использовать регулярное выражение для анализа вашего текста:

str = "Title: My Treatise on Kumquats
Author: Joe Schmoe
Author URL: http://somedudeswebsite.me/
Host URL: http://googlesnewthing.com/
Created: 2012-01-01 09:41"

matches = str.scan /^(.+?): (.+?)$/m

matches.each { |m|
   key = m[0]
   value = m[1]
}

Это регулярное выражение с несколькими строками (/<regex>/m) - каждая строка будет сопоставляться в две группы (с индексами 0 и 1).Первая группа будет содержать все символы до первого вхождения ": " (двоеточие + пробел).Вторая группа будет содержать все остальные символы в этой строке (до тех пор, пока регулярное выражение не встретит конец строки $).

Вот как можно преобразовать результат в хэш:

dictionary = matches.inject({}) do |dict, m| 
  dict[m[0]] = m[1]
  dict
end

ОБНОВЛЕНИЕ

Как упоминал Майкл Кол, можно написать это в одной строке:

hash = Hash[str.scan /^(.+?): (.+?)$/m]
0 голосов
/ 18 января 2012

Является ли line.split(':',2) тем, что вы хотите?

String # split принимает второй аргумент, который указывает части, которые должны быть разделены. он работает в ruby ​​1.9.3, не уверен в более ранних версиях. (но я почти уверен, что это также работает в 1.9.2)

Если это недоступно, line.scan(%r{^([^:]*):(.*)}) также должно работать.

0 голосов
/ 18 января 2012

Вы можете просто сделать это,

>> s = 'Author URL: http://somedudeswebsite.me/'
>> first_idx = s.index(':')
>> key,value = s[0..first_idx-1],s[first_idx+1..s.length]
=> ["Author URL", " http://somedudeswebsite.me/"]

или к хэшу ключевого значения по

>> kv = Hash[*s[0..first_idx-1],s[first_idx+1..s.length]]
=> {"Author URL"=>" http://somedudeswebsite.me/"}

Надеюсь, это поможет

...