2016-05-30 22 views
9

Haftungsausschluss: Ich habe dies über PerlMonks Cross-Posted.Perl6: Erfassen von Windows-Zeilenumbruch in einer Zeichenfolge mit Regex

In Perl5, ich kann schnell und einfach die hexadezimale Darstellung der Endung \r\n im Windows-Stil Linie ausdrucken:

perl -nE '/([\r\n]{1,2})/; print(unpack("H*",$1))' in.txt 
0d0a 

ein Windows-ending-Datei auf Unix erstellen, wenn Sie testen möchten, erstellen in.txt Datei mit einer einzelnen Zeile und Zeilenende. Dann: perl -ni -e 's/\n/\r\n/g;print' in.txt. (oder in vi/vim, erstellen Sie die Datei und tun Sie einfach :set ff=dos).

Ich habe viele Dinge in Perl6 versucht, das Gleiche zu tun, aber ich kann es nicht zum Laufen bringen, egal was ich tue. Hier ist mein letzter Test:

use v6; 
use experimental :pack; 

my $fn = 'in.txt'; 

my $fh = open $fn, chomp => False; # I've also tried :bin 
for $fh.lines -> $line { 
    if $line ~~ /(<[\r\n]>**1..2)/ { 
     $0.Str.encode('UTF-8').unpack("H*").say; 
    } 
} 

Ausgänge 0a, wie tun:

/(\n)/ 
/(\v)/ 

Erstens, ich weiß nicht einmal, ob ich unpack() oder die Regex richtig bin mit. Zweitens, wie erfasse ich beide Elemente (\r\n) des Newline in P6?

+2

In Perl5, ziehe ich 'sprintf ("% v02X", $ s)'. Funktioniert für jede Zeichenfolge, nicht nur für Bytefolgen. – ikegami

Antwort

5

Perl 6 schaltet automatisch den Zeilentrenner für Sie aus. Was bedeutet, dass es nicht da ist, wenn Sie versuchen, eine Substitution zu machen.

Perl 6 erstellt auch synthetische Zeichen, wenn Zeichen kombiniert werden. Wenn Sie also eine Basis 16-Darstellung Ihrer Eingabe wünschen, verwenden Sie die Codierung 'latin1' oder verwenden Sie Methoden auf $*IN, die einen Buf zurückgeben.


In diesem Beispiel wird CRLF nur an das Ende jeder Zeile angehängt.
(Die letzte Zeile wird immer mit 0D 0A sogar am Ende, wenn es nicht hat einen Leitungsabschluss) ausschalten

perl6 -ne 'BEGIN $*IN.encoding("latin1"); #`(basically ASCII) 
    $_ ~= "\r\n"; #`(append CRLF) 
    put .ords>>.fmt("%02X");' 

Sie könnten auch das autochomp Verhalten.

perl6 -ne 'BEGIN { 
     $*IN.encoding("latin1"); 
     $*IN.chomp = False; 
    }; 
    s/\n/\r\n/; 
    put .ords>>.fmt("%02X");' 
1

Ok, so was mein Ziel war (ich bin traurig, dass ich nicht, dass deutlich machen, wenn ich gepostet die Frage) war ich möchte eine Datei lesen, die Zeilenende erfassen, und schreiben Sie die Datei zurück Verwenden Sie die ursprünglichen Zeilenenden (und nicht die Endungen für die aktuelle Plattform).

Ich habe jetzt einen Proof of Concept bekommen. Ich bin sehr neu in Perl 6, also ist der Code wahrscheinlich nicht sehr p6-ish, aber er tut, was ich brauchte.

-Code auf FreeBSD getestet:

use v6; 
    use experimental :pack; 

    my $fn = 'in.txt'; 
    my $outfile = 'out.txt'; 

    # write something with a windows line ending to a new file 

    my $fh = open $fn, :w; 
    $fh.print("ab\r\ndef\r\n"); 
    $fh.close; 

    # re-open the file 

    $fh = open $fn, :bin; 

    my $eol_found = False; 
    my Str $recsep = ''; 

    # read one byte at a time, or else we'd have to slurp the whole 
    # file, as I can't find a way to differentiate EOL from EOF 

    while $fh.read(1) -> $buf { 
     my $hex = $buf.unpack("H*"); 
     if $hex ~~ /(0d|0a)/ { 
      $eol_found = True; 
      $recsep = $recsep ~ $hex; 
      next; 
     } 
     if $eol_found { 
      if $hex !~~ /(0d|0a)/ { 
       last; 
      } 
     } 
    } 

    $fh.close; 

    my %recseps = (
     '0d0a' => "\r\n", 
     '0d' => "\r", 
     '0a' => "\n", 
    ); 

    my $nl = %recseps<<$recsep>>; 

    # write a new file with the saved record separator 

    $fh = open $outfile, :w; 
    $fh.print('a' ~ $nl); 
    $fh.close; 

    # re-read file to see if our newline stuck 

    $fh = open $outfile, :bin; 

    my $buf = $fh.read(1000); 
    say $buf; 

Ausgang:

Buf[uint8]:0x<61 0d 0a> 
+0

Ich gehe zurück zu Intro/Docs, dann, nachdem ich besser geübt bin, teste es erneut mit meinem neuen Wissen. – stevieb

+0

Ist [newline.t] (https://github.com/perl6/roast/S16-io/newline.t) aus [braten] (https://github.com/perl6/roast/blob/master/README) hilfreich? – raiph

+0

Auf jeden Fall! Vielen Dank. Tatsächlich habe ich nicht einmal daran gedacht, die Testdateien nach Beispielen zu betrachten, aber die ganze Suite wird ein enormes Lernwerkzeug sein. – stevieb