2016-07-10 7 views
1

Ich muss eine Textdatei mit dem folgenden Format analysieren und es in einen Hash konvertieren, der in JSON konvertiert wird.Wie man eine Textdatei analysiert, die mehrere Zeilen von Daten enthält und durch numerische Werte organisiert und dann zu JSON konvertiert

Die Textdatei hat folgendes Format:

HD040008000415350110XXXXXXXXXX0208XXXXXXXX0302EN0403USA0502EN0604000107014 
EM04000800030010112TME001205IQ50232Blue Point Coastal Cuisine. INC.06145655th Avenue0805921010909SAN DIEGO1008Downtown1102CA1203USA 

Jede Linie ist eine Gruppe von Segmenten, die mit einem Schlüsselwert-Format arbeiten. Beispielsweise würde die zweite Zeile sein:

  • EM Schlüssel ist
  • 04 ist die Länge des Wertes einschließlich Leerzeichen
  • 0008 ist der Wert

es oben brechen, wäre es so aussehen EM 04 0008. Die nächsten Segmenttasten sind numerisch und beginnen mit 00 und erhöhen sich dann bis zum Ende der Zeile, die dann von vorne beginnen würde. Ich müsste jede einzelne Zeile in einer Textdatei durchlaufen.

Ich muss in der Lage sein, dies in einen Ruby-Hash zu konvertieren, der wiederum in JSON in einer API-Antwort konvertiert werden würde.

würde das aktuelle Format sein:

EM0400080003001 

Es müssten und in der sie analysiert:

{"EM" => 0008, "00" => "001"} 
+0

Könnten Sie ein paar Zeilen zur Verfügung stellen (3-4) der Textdatei und den genauen Ausgang (in json oder Hash), die Sie sehen sind für? Es ist immer noch etwas unklar, da hinter EM0400080003001 eine Menge Dinge sind (außer sie werden ignoriert). Auch unsicher, ob EM eine Ziffer sein kann oder nicht, usw. –

+0

EM0400080003001 ist nur ein Beispiel für das Format. Die vollständige Zeichenfolge muss in einen Ruby-Hashwert zerlegt werden. –

+0

Jede Zeile kann nur mit Buchstaben beginnen. Wie in den beiden Zeilen sind die HD und EM aber es könnte LS, GH, MN etc. sein. –

Antwort

2

Dies ist eine sehr häufige Art der Codierung Type-Length-Value (oder Tag-Length-Value) genannt, aus Gründen, nehme ich an sind offensichtlich. Wie bei vielen solcher Aufgaben in Ruby, ist String#unpack eine gute Passform:

def decode(data) 
    return {} if data.empty? 
    key, len, rest = data.unpack("a2 a2 a*") 
    val = rest.slice!(0, len.to_i) 
    { key => val }.merge(decode(rest)) 
end 

p decode("HD040008000415350110XXXXXXXXXX0208XXXXXXXX0302EN0403USA0502EN0604000107014") 
# => {"HD"=>"0008", "00"=>"1535", "01"=>"XXXXXXXXXX", "02"=>"XXXXXXXX", "03"=>"EN", "04"=>"USA", "05"=>"EN", "06"=>"0001", "07"=>"4"} 

p decode("EM04000800030010112TME001205IQ50232Blue Point Coastal Cuisine. INC.0614565 5th Avenue0805921010909SAN DIEGO1008Downtown1102CA1203USA") 
# => {"EM"=>"0008", "00"=>"001", "01"=>"TME001205IQ5", "02"=>"Blue Point Coastal Cuisine. INC.", "06"=>"565 5th Avenue", "08"=>"92101", "09"=>"SAN DIEGO", "10"=>"Downtown", "11"=>"CA", "12"=>"USA"} 

Wenn Sie eine ganze Datei und gibt eine JSON Array von Objekten zu lesen, so etwas wie dies würde genügen:

#!/usr/bin/env ruby -n 
BEGIN { 
    require "json" 
    def decode(data) 
    # ... 
    end 
    arr = [] 
} 

arr << decode($_.chomp) 

END { puts arr.to_json } 

dann ist (das Skript angenommen genannt wird script.rb und ausführbar ist:

$ cat data.txt | ./script.rb > out.json 
+0

Das ist genial! Vielen Dank. –

1

die Länge Unter der Annahme, 2 Zeichen für den Schlüssel und 2 Ziffern für:

line = "EM04000800030010112TME001205IQ50232Blue Point Coastal Cuisine. INC.06145655th Avenue0805921010909SAN DIEGO1008Downtown1102CA1203USA" 



hsh = {} 
arr = line.chars 
until arr.empty? 
    key = arr.shift(2).join 
    length = arr.shift(2).join.to_i 
    value = arr.shift(length).join 
    hsh[key] = value 
end 
hsh 

=> {"EM"=>"0008", "00"=>"001", "01"=>"TME001205IQ5", "02"=>"Blue Point Coastal Cuisine. INC.", "06"=>"5655th Avenue0", "80"=>"21010909SAN DIEGO1008Downtown1102CA1203USA"} 

Die Ergebnisse sehen irgendwie funky aus.

EDIT - durch die Datei Schritt Sie es öffnen müssen Sie wie folgt vor:

File.open(filename).each_line do |line| 
    do stuff with line here 
end 
+0

Wow, das könnte es sein. Ich habe es versucht, wie du gesagt hast, es ist irgendwie funky, aber es ist ein Schritt in die richtige Richtung. Ich müsste das für jede einzelne Zeile machen können. Was wäre der effizienteste Weg, dies zu tun? –

+0

'" 06 "=>" 5655. Avenue0 "ist falsch und es wirft alles danach ab. Ich glaube, es sollte "565 5th Avenue" oder "56 55th Avenue" sein. Hoffentlich nur ein Problem durch Kopieren und Einfügen. Um die Datei zu verarbeiten, müssen Sie sie nur Zeile für Zeile lesen. Ich werde meine Antwort bearbeiten, um das zu berücksichtigen. – seph

+0

Ja, Sie haben die Ergebnisse von 06 richtig. Danke für Ihre Hilfe. Es ist ein Schritt in die richtige Richtung. –