2016-03-14 3 views
-3

У меня есть эти Syslog сообщения:Синтаксический строковое поле

N 4000000 PROD  15307 23:58:12.13 JOB78035 00000000 $HASP395 GGIVJS27 ENDED\r 
NI0000000 PROD  15307 23:58:13.41 STC81508 00000200 $A J78036   /* CA-JOBTRAC JOB RELEASE */\r 

Я хотел бы разобрать эти сообщения в различных областях в Hash, например:

event['recordtype'] #=> "N" 
event['routingcode'] #=> "4000000" 
event['systemname'] #=> "PROD" 
event['datetime'] #=> "15307 23:58:12.13" 
event['jobid']  #=> "JOB78035" 
event['flag']  #=> "00000000" 
event['messageid'] #=> "$HASP395" 
event['logmessage'] #=> "$HASP395 GGIVJS27 ENDED\r" 

Это код, я в настоящее время :

message = event["message"]; 
if message.to_s != "" then 
    if message[2] == " " then 
    array = message.split(%Q[ ]); 
    event[%q[recordtype]] = array[0]; 
    event[%q[routingcode]] = array[1]; 
    event[%q[systemname]] = array[2]; 
    event[%q[datetime]] = array[3] + " " +array[4]; 
    event[%q[jobid]] = message[38,8]; 
    event[%q[flags]] = message[47,8]; 
    event[%q[messageid]] = message[57,8]; 
    event[%q[logmessage]] = message[56..-1]; 
    else 
    array = message.split(%Q[ ]); 
    event[%q[recordtype]] = array[0][0,2]; 
    event[%q[routingcode]] = array[0][2..-1]; 
    event[%q[systemname]] = array[1]; 
    event[%q[datetime]] = array[2] + " "+array[3]; 
    event[%q[jobid]] = message[38,8]; 
    event[%q[flags]] = message[47,8]; 
    event[%q[messageid]] = message[57,8]; 
    event[%q[logmessage]] = message[56..-1]; 
    end 
end 

Я ищу, чтобы улучшить приведенный выше код. Я думаю, что могу использовать регулярное выражение, но я не знаю, как подойти к нему.

+1

Можете ли вы привести пример хэш-карты, которую вы хотели бы создать? –

+2

Что такое 'event'? – sawa

+2

Почему вы используете '% q [...]' и '% Q [...]' литералы? – Stefan

ответ

2

Вы не можете использовать split(' ') или по умолчанию split для обработки ваших полей, потому что вы имеете дело со столбчатыми данными, у которых есть поля, которые не имеют пробелов между ними, в результате чего ваш массив выключен. Вместо этого вам приходится выделять каждую запись по столбцам.

Есть много способов сделать это, но самый простой и, вероятно, самый быстрый, индексирует в строку и захват п символов:

'foo'[0, 1] # => "f" 
'foo'[1, 2] # => "oo" 

Первые средства «, начиная с индекса 0 в строке, возьмите один символ «. Второй означает «начиная с индекса 1 в строке, захватить два символа».

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

'foo'[0 .. 0] # => "f" 
'foo'[1 .. 2] # => "oo" 

Это documented in the String class.

Это делает написание кода, который легко понять:

record_type = message[ 0 .. 1 ].rstrip 
routing_code = message[ 2 .. 8 ] 
system_name = message[ 10 .. 17 ] 

После того как вы ваши поля захватили добавить их в хеш:

{ 
    'recordtype' => record_type, 
    'routingcode' => routing_code, 
    'systemname' => system_name, 
    'datetime' => date_time, 
    'jobid'  => job_id, 
    'flags'  => flags, 
    'messageid' => message_id, 
    'logmessage' => log_message, 
} 

В то время как вы могли бы использовать регулярное выражение, там не так много получить, используя один, это просто еще один способ сделать это. Если бы вы выбрали данные из текста свободной формы, это было бы более полезно, но в столбчатых данных оно, как правило, приводит к визуальному шуму, который затрудняет обслуживание. Я бы рекомендовал просто определить ваши столбцы, а затем сократить нужные вам данные на основе данных из каждой строки.

+0

Вы можете сделать еще один шаг и определить поля как диапазоны в шаблоне, такие как 'recordtype: 0..1, routing_code: 2..8', а затем использовать их для извлечения всех полей с помощью' map' и 'Hash [ ] '. – tadman

+0

Да, но я не хотел подавлять ОП, поэтому я решил, что лучше всего начать с простого извлечения текста. –

+0

Наверняка! Просто показывая, как это можно повторить еще немного. Ruby делает так, что tranforms довольно элегантно и просто. – tadman

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