Get the value of an auto-splitting separator?

If I run the script with perl -F something, something the value is stored anywhere in the Perl environment, where can the script find it? I would like to write a script that by default reuses the input separator (if it is a string, not a regular expression) as the output separator.

+5
source share
2 answers

Looking at the source , I don't think the delimiter is stored anywhere. When you run

 perl -F, -an 

lexer actually generates code

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

and analyzes it. At this point, all information about the separator is lost.


Your best option is manual split :

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

or pass a separator as an argument to your script:

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

or pass the delimiter as an environment variable:

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

As @ThisSuitIsBlackNot says it looks like the delimiter is stored anywhere.

This is how perl.c stores the -F option

 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; 

And then lexer generates code

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

However, this is of course compiled, and if you run it using B :: Deparse, you will see what is stored.

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

Being perl, there is always a way, no matter how ugly. (And this is one of the ugliest codes I wrote after a while):

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

Output:

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

Instead, you can skip to the bytecode, as the launch is likely to be the same every time you reach the template.

0
source

Source: https://habr.com/ru/post/1243977/


All Articles