Wie entferne ich Wagenrückläufe mit Ruby?

75

Ich dachte, dieser Code würde funktionieren, aber der reguläre Ausdruck stimmt nie mit dem \ r \ n überein. Ich habe die Daten, die ich lese, in einem Hex-Editor angezeigt und überprüft, ob die Datei wirklich ein Hex-D- und ein Hex-A-Muster enthält.

Ich habe auch die regulären Ausdrücke / \ xD \ xA / m und / \ x0D \ x0A / m ausprobiert, aber sie stimmten auch nicht überein.

Dies ist jetzt mein Code:

   lines2 = lines.gsub( /\r\n/m, "\n" )
   if ( lines == lines2 )
       print "still the same\n"
   else
       print "made the change\n"
   end

Zusätzlich zu Alternativen wäre es schön zu wissen, was ich falsch mache (um meinerseits das Lernen zu erleichtern). :) :)

Jeremy Mullin
quelle

Antworten:

23

Was bekommen Sie, wenn Sie tun puts lines? Das gibt Ihnen einen Hinweis.

Standardmäßig File.openwird die Datei im Textmodus geöffnet, sodass Ihre \r\nZeichen automatisch in konvertiert werden \n. Vielleicht ist das der Grund, warum sie linesimmer gleich sind lines2. Verwenden Sie den folgenden rbModus, um zu verhindern, dass Ruby die Zeilenenden analysiert :

C: \> copy con lala.txt
ein
Datei
mit
viele
Linien
^ Z.

C: \> irb
irb (main): 001: 0> text = File.open ('lala.txt'). read
=> "a \ nDatei \ nmit \ nVielen \ nZeilen \ n"
irb (main): 002: 0> bin = File.open ('lala.txt', 'rb'). read
=> "a \ r \ nDatei \ r \ nmit \ r \ nviel \ r \ nLinien \ r \ n"
irb (main): 003: 0>

Aus Ihrer Frage und Ihrem Code geht jedoch hervor, dass Sie die Datei lediglich mit dem Standardmodifikator öffnen müssen. Sie benötigen keine Konvertierung und können die kürzere verwenden File.read.

Rômulo Ceccon
quelle
2
Es gibt eine Antwort mit mehr positiven Stimmen, die auf die "Strip Newlines" weiter unten ausgerichtet sind: stackoverflow.com/a/7095275/403234
yas4891
167

Verwenden Sie String # strip

Gibt eine Kopie von str zurück, wobei führende und nachfolgende Leerzeichen entfernt wurden.

z.B

"    hello    ".strip   #=> "hello"   
"\tgoodbye\r\n".strip   #=> "goodbye"

Mit gsub

string = string.gsub(/\r/," ")
string = string.gsub(/\n/," ")
Ian Vaughan
quelle
5
Es werden keine Zeilenumbrüche in der Mitte des Textes gefiltert: "line1 \ n line2" .strip # => "line1 \ n line2"
ndrix
Wenn es innerhalb eines each_lineAnrufs verwendet wird, spielt das keine Rolle.
Ian Vaughan
9
Entfernen aller umgebenden Leerzeichen! = Entfernen von Wagenrückläufen
Barry Kelly
35

Wenn ich mich mit Strippen oder \ n beschäftige, suche ich im Allgemeinen nach beidem, indem ich so etwas mache

lines.gsub(/\r\n?/, "\n");

Ich habe festgestellt, dass je nachdem, wie die Daten gespeichert wurden (das verwendete Betriebssystem, der verwendete Editor, Jupiters Beziehung zu Io zu der Zeit), nach dem Wagenrücklauf möglicherweise die neue Zeile vorhanden ist oder nicht. Es scheint seltsam, dass Sie beide Zeichen im Hex-Modus sehen. Hoffe das hilft.

Einheimische
quelle
21

Wenn Sie Rails verwenden, gibt es eine squishMethode

"\tgoodbye\r\n".squish => "goodbye"

"\tgood \t\r\nbye\r\n".squish => "good bye"

Hals
quelle
Das ist ein toller Tipp!
Bryanus
2
Für Nicht-Rails-Benutzer ist es implementiert alsstr.gsub(/[[:space:]]+/, ' ').strip
sobstel
17
modified_string = string.gsub(/\s+/, ' ').strip
Vik
quelle
Danke vielmals! Es rettet meinen Tag!
Rubyrider
2
Dies ersetzt alle Leerzeichen, nicht nur CR / LFs
hoffmanc
15
lines2 = lines.split.join("\n")
Cameron Price
quelle
4
Dadurch werden auch Tabulatoren und Leerzeichen entfernt, was möglicherweise nicht den Wünschen des Benutzers entspricht.
Doug
6

Wie wäre es mit folgendem?

irb(main):003:0> my_string = "Some text with a carriage return \r"
=> "Some text with a carriage return \r"
irb(main):004:0> my_string.gsub(/\r/,"")
=> "Some text with a carriage return "
irb(main):005:0>

Oder...

irb(main):007:0> my_string = "Some text with a carriage return \r\n"
=> "Some text with a carriage return \r\n"
irb(main):008:0> my_string.gsub(/\r\n/,"\n")
=> "Some text with a carriage return \n"
irb(main):009:0>
mwilliams
quelle
Außerdem habe ich Folgendes überprüft: "\ r \ n"! = "\ n". Es sieht also so aus, als ob der ursprüngliche Postercode richtig ist.
Rampion
4

Ich denke, Ihre Regex ist fast vollständig - hier ist, was ich tun würde:

lines2 = lines.gsub(/[\r\n]+/m, "\n")

Oben habe ich \ r und \ n in eine Klasse eingefügt (auf diese Weise spielt es keine Rolle, in welcher Reihenfolge sie erscheinen) und das Qualifikationsmerkmal "+" hinzugefügt (so dass "\ r \ n \ r \ n" \ r \ n "würde auch einmal übereinstimmen, und das Ganze durch" \ n "ersetzt)

Nathan Crause
quelle
3

Nur eine andere Variante:

lines.delete(" \n")
k1r8r0wn
quelle
2

Warum lesen Sie die Datei nicht im Textmodus und nicht im Binärmodus?

Andrew Grimm
quelle
1

Sie können dies verwenden:

my_string.strip.gsub(/\s+/, ' ')
Alain Beauvois
quelle
1
Im Wesentlichen die gleiche Antwort wie diese oben.
Stellen Sie Monica wieder her - notmaynard
1
lines.map(&:strip).join(" ")
frenesim
quelle
0
def dos2unix(input)
  input.each_byte.map { |c| c.chr unless c == 13 }.join
end

remove_all_the_carriage_returns = dos2unix(some_blob)
Dennis
quelle