2016-05-30 19 views
9

Dichiarazione di non responsabilità: l'ho posticipato a PerlMonks.Perl6: Cattura di una nuova riga di Windows in una stringa con espressione regolare

In Perl5, posso rapidamente e facilmente stampare la rappresentazione esadecimale della linea \r\n stile Windows chiusura

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

Per creare un file di Windows senza fine su Unix, se si vuole testare, creare un in.txt file con una singola riga e una fine riga. Quindi: perl -ni -e 's/\n/\r\n/g;print' in.txt. (o in vi/vim, crea il file e fai semplicemente :set ff=dos).

Ho provato molte cose in Perl6 a fare la stessa cosa, ma non riesco a farlo funzionare, non importa quello che faccio. Ecco la mia prova più recente:

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; 
    } 
} 

Uscite 0a, come fare:

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

In primo luogo, io non so nemmeno se sto usando unpack() o l'espressione regolare in modo corretto. In secondo luogo, come posso acquisire entrambi gli elementi (\r\n) della nuova riga in P6?

+2

In Perl5, preferisco 'sprintf ("% v02X", $ s)'. Funziona per qualsiasi stringa, non solo stringhe di byte. – ikegami

risposta

5

Perl 6 blocca automaticamente il separatore di linee per te. Il che significa che non è lì quando provi a fare una sostituzione.

Perl 6 crea anche caratteri sintetici se sono presenti caratteri combinati. quindi se si desidera una rappresentazione di base 16 del proprio input, utilizzare la codifica 'latin1' o utilizzare i metodi su $*IN che restituiscono un Buf.


Questo esempio aggiunge semplicemente CRLF alla fine di ogni riga.
(L'ultima riga sarà sempre terminare con 0D 0A anche se non ha avuto un terminatore di linea)

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

Si potrebbe anche spegnere il comportamento autochomp.

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

Ok, quindi ciò che il mio obiettivo è stato (mi dispiace non ho fatto che chiaro quando ho postato la domanda) è stato Voglio leggere un file, catturare i fine riga, e scrivere il file indietro utilizzando le terminazioni di linea originali (e non le terminazioni per la piattaforma corrente).

Ho ottenuto una dimostrazione del concetto di lavoro ora. Sono molto nuovo a Perl 6, quindi il codice probabilmente non è molto p6-ish, ma fa quello che mi serviva.

codice testato su FreeBSD:

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; 

uscita:

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

Tornerò a esaminare i documenti introduttivi/doc, quindi, dopo che sarò più abile, riprovo con le mie nuove conoscenze. – stevieb

+0

È [newline.t] (https://github.com/perl6/roast/S16-io/newline.t) da [arrosto] (https://github.com/perl6/roast/blob/master/README) utile? – raiph

+0

Più decisamente! Grazie mille. In effetti, non ho nemmeno pensato di guardare i file di test per gli esempi, ma l'intera suite sarà un enorme strumento di apprendimento. – stevieb

Problemi correlati