I want to extract rows 1 to n from my .csv file. Using this
perl -ne 'if ($. == 3) {print;exit}' infile.txt
I can extract only开发者_如何学运维 one row. How to put a range of rows into this script?
If you have only a single range and a single, possibly concatenated input stream, you can use:
#!/usr/bin/perl -n
if (my $seqno = 1 .. 3) {
print;
exit if $seqno =~ /E/;
}
But if you want it to apply to each input file, you need to catch the end of each file:
#!/usr/bin/perl -n
print if my $seqno = 1 .. 3;
close ARGV if eof || $seqno =~ /E/;
And if you want to be kind to people who forget args, add a nice warning in a BEGIN
or INIT
clause:
#!/usr/bin/perl -n
BEGIN { warn "$0: reading from stdin\n" if @ARGV == 0 && -t }
print if my $seqno = 1 .. 3;
close ARGV if eof || $seqno =~ /E/;
Notable points include:
You can use
-n
or-p
on the#!
line. You could also put some (but not all) other command line switches there, like‑l
or‑a
.Numeric literals as operands to the scalar flip‐flop operator are each compared against
readline
counter, so a scalar1 .. 3
is really($. == 1) .. ($. == 3)
.Calling
eof
with neither an argument nor empty parens means the last file read in the magicARGV
list of files. This contrasts witheof()
, which is the end of the entire<ARGV>
iteration.A flip‐flop operator’s final sequence number is returned with a
"E0"
appended to it.The
-t
operator, which calls libc’sisatty(3)
, default to theSTDIN
handle — unlike any of the other filetest operators.A
BEGIN{}
block happens during compilation, so if you try to decompile this script with‑MO=Deparse
to see what it really does, that check will execute. With anINIT{}
, it will not.Doing just that will reveal that the implicit input loop as a label called
LINE
that you perhaps might in other circumstances use to your advantage.
HTH
What's wrong with:
head -3 infile.txt
If you really must use Perl then this works:
perl -ne 'if ($. <= 3) {print} else {exit}' infile.txt
You can use the range operator:
perl -ne 'if (1 .. 3) { print } else { last }' infile.txt
精彩评论