Regex sind rutschige kleine Dinge, und je größer sie sind, desto wahrscheinlicher sind sie außer Kontrolle geraten.
ich so etwas tun würde:
input = <<EOT
| Percentage Range |
|------------------|
| 17 - 20.4% |
| 7 - 20.4% |
EOT
input.lines[2 .. -1].map{ |l| l.scan(/[\d.]+/) }
# => [["17", "20.4"], ["7", "20.4"]]
Der Kern ist dies die regex /[\d.]+/
in scan
, was im Grunde bedeutet: Hier finden Sie Zahlen und Dezimal-Punkte.
Hier ist eine Aufschlüsselung das, was geschieht:
input.lines
# => ["| Percentage Range |\n", "|------------------|\n", "| 17 - 20.4% |\n", "| 7 - 20.4% |\n"]
lines
teilt eine Zeichenfolge auf seinem eingebetteten Line-Enden, eine Reihe von Linien zurück.
input.lines[2 .. -1]
# => ["| 17 - 20.4% |\n", "| 7 - 20.4% |\n"]
Das gibt die Zeilen zurück, die wir wollen.
Sie sollten in der Lage sein, den Rest herauszufinden.
auf dem Code der Suche:
@sample_data.each do ||
low_value = p.percentage_range.gsub('regex goes here') #17 for ex
high_value = p.percentage_range.gsub('regex goes here') #20.4 for example
end
Es gibt mehrere Dinge falsch:
||
ist nicht notwendig, noch Ihr Code hilft verständlicher sein.
- Was ist ?
- Was ist
percentage_range
?
gsub
ist eine globale Substitution zu tun, und ist hier unpassend. Ersetze Sachen nicht, wenn du passen/finden willst. Es gibt einen großen Unterschied im Zweck und normalerweise wird man den anderen nicht ersetzen.
Wenn Sie nicht wollen, scan
verwenden, die die offensichtliche Go-to-Methode hierfür ist:
scan(pattern)
→ Array
[...]
Beide Formen iterieren durch str und stimmen mit dem Muster überein (das ein Regexp oder ein String sein kann). Für jede Übereinstimmung wird ein Ergebnis generiert und entweder zum Ergebnis-Array hinzugefügt oder an den Block übergeben. Wenn das Muster keine Gruppen enthält, besteht jedes einzelne Ergebnis aus der übereinstimmenden Zeichenfolge $ &. Wenn das Muster Gruppen enthält, ist jedes einzelne Ergebnis selbst ein Array, das einen Eintrag pro Gruppe enthält.
a = "cruel world"
a.scan(/\w+/) #=> ["cruel", "world"]
a.scan(/.../) #=> ["cru", "el ", "wor"]
a.scan(/(...)/) #=> [["cru"], ["el "], ["wor"]]
a.scan(/(..)(..)/) #=> [["cr", "ue"], ["l ", "wo"]]
dann könnte man andere Möglichkeiten, die Daten verwenden, greifen:
low, high = '17 - 20.4%'.scan(/[\d.]+/)
# => ["17", "20.4"]
low, high = '17 - 20.4%'.match(/([\d.]+)\s+-\s+([\d.]+)/).captures
# => ["17", "20.4"]
low, high = '17 - 20.4%'.tr(' %', '').split('-')
# => ["17", "20.4"]
Beachten Sie, dass das Muster für match
viel komplexer ist und weniger lesbar. Es könnte etwas werden mit Variationen vereinfacht wie:
low, high = '17 - 20.4%'.match(/([\d.]+).+?([\d.]+)%/).captures
# => ["17", "20.4"]
aber scan
bleibt mehr einfach und auf den Punkt und verwendet ein triviales Muster.
Dieser Ausschnitt oben ist ein Textblock, richtig? –
@AnthonyE Dies ist nur ein Beispiel für die Daten aus einer Tabelle, die ich importiere. Ich möchte es in zwei Spalten extrahieren, wenn Sie in meine Rails-App importieren – ctilley79
Willkommen bei Stack Overflow. Bitte lesen Sie "[fragen]" und "[mcve]". Wir würden gerne Ihre Bemühungen sehen, dies zu lösen. Welchen Code hast du geschrieben, um das Problem zu lösen? Warum hat es nicht funktioniert? Wie es aussieht, möchten Sie, dass wir den Code für Sie schreiben, der nicht der Stack-Overflow-Weg ist. Fügen Sie den Mindestcode hinzu, der zur Veranschaulichung des Problems erforderlich ist. –