2016-02-26 15 views
5

Se eseguo uno script con perl -Fqualcosa di, è quello qualcosa di valore salvato in un ambiente Perl dove lo script può trovarlo? Mi piacerebbe scrivere uno script che riutilizza di default il delimitatore di input (se si tratta di una stringa e non di un'espressione regolare) come delimitatore di output.Ottieni il valore del delimitatore autosplit?

risposta

4

Guardando allo source, non penso che il delimitatore sia stato salvato da nessuna parte. Quando si esegue

perl -F, -an 

il lexer in realtà genera il codice

LINE: while (<>) {our @F=split(q\0,\0); 

e lo analizza. A questo punto, qualsiasi informazione sul delimitatore viene persa.


La soluzione migliore è quella di split a mano:

perl -ne'BEGIN { $F="," } @F=split(/$F/); print join($F, @F)' foo.csv 

o per passare il delimitatore come argomento per lo script:

F=,; perl -F$F -sane'print join($F, @F)' -- -F=$F foo.csv 

o per passare il delimitatore come ambiente variabile:

export F=,; perl -F$F -ane'print join($ENV{F}, @F)' foo.csv 
+0

Questo è quello che temevo. Grazie. –

+1

BTW, 'perl -F, -an' è tecnicamente ridondante; '-F' di per sé implica sia' -a' che '-n' (che puoi sovrascrivere specificando manualmente' -p'). Probabilmente è più chiaro includerli, sebbene la chiarezza non sia in genere una priorità quando si scrive un one-liner anziché uno script da salvare. :) –

0

Come @ThisSuitIsBlackNot dice che sembra che il delimitatore sia stato salvato ovunque.

questo è come il perl.c memorizza il parametro -F

case 'F': 
PL_minus_a = TRUE; 
PL_minus_F = TRUE; 
    PL_minus_n = TRUE; 
PL_splitstr = ++s; 
while (*s && !isSPACE(*s)) ++s; 
PL_splitstr = savepvn(PL_splitstr, s - PL_splitstr); 
return s; 

e poi il lexer genera il codice

LINE: while (<>) {our @F=split(q\0,\0); 

tuttavia questo è ovviamente compilato, e se lo si esegue con B :: Sparse puoi vedere cosa viene memorizzato.

$ perl -MO=Deparse -F/e/ -e '' 
LINE: while (defined($_ = <ARGV>)) { 
    our(@F) = split(/e/, $_, 0); 
} 
-e syntax OK 

Essere perl c'è sempre un modo, per quanto brutto. (E questo è parte del codice più brutto che ho scritto in un po '):

use B::Deparse; 
use Capture::Tiny qw/capture_stdout/; 
BEGIN { 
    my $f_var; 
} 

unless ($f_var) { 
    $stdout = capture_stdout { 
     my $sub = B::Deparse::compile(); 
     &{$sub}; # Have to capture stdout, since I won't bother to setup compile to return the text, instead of printing 
    }; 

    my (undef, $split_line, undef) = split(/\n/, $stdout, 3); 
    ($f_var) = $split_line =~ /our\(\@F\) = split\((.*)\, \$\_\, 0\);/; 
    print $f_var,"\n"; 
} 

uscita:

$ perl -Fe/\\\(\\[\\\<\\{\"e testy.pl 
m#e/\(\[\<\{"e# 

Si potrebbe possibile attraversare il bytecode, invece, fin dall'inizio, probabilmente sarà identico ogni volta fino a raggiungere il modello.

+0

Beh, è ​​impressionante, ma un po 'eccessivo per la mia applicazione. Farò solo la divisione non automatica. –

Problemi correlati