Каков slickest способ программно читать из stdin или входного файла (если предоставлено) в Perl?
while (<>) {
print;
}
будет читаться либо из файла, указанного в командной строке, либо из stdin, если файл не указан
Если вам нужна эта конструкция цикла в командной строке, вы можете использовать опцию -n
:
$ perl -ne 'print;'
Здесь вы просто помещаете код между {}
из первого примера в ''
во второй
Это обеспечивает именованную переменную для работы с:
foreach my $line ( <STDIN> ) {
chomp( $line );
print "$line\n";
}
Чтобы прочитать файл, проведите его так:
program.pl < inputfile
Вам нужно использовать < > operator:
while (<>) {
print $_; # or simply "print;"
}
который может быть спрессован до:
print while (<>);
Произвольный файл:
open F, "<file.txt" or die $!;
while (<F>) {
print $_;
}
close F;
В некоторых ситуациях "скользкий" способ заключается в использовании переключателя -n
. Он неявно обертывает ваш код циклом while(<>)
и гибко управляет входным сигналом.
В slickestWay.pl
:
#!/usr/bin/perl -n BEGIN: { # do something once here } # implement logic for a single line of input print $result;
В командной строке:
chmod +x slickestWay.pl
Теперь, в зависимости от вашего ввода, выполните одно из следующих действий:
Дождитесь ввода пользователем
./slickestWay.pl
Чтение из файлов, названных в аргументах (не требуется перенаправление)
./slickestWay.pl input.txt
./slickestWay.pl input.txt moreInput.txt
Используйте трубку
someOtherScript | ./slickestWay.pl
Блок BEGIN
необходим, если вам нужно инициализировать какой-то объектно-ориентированный интерфейс, такой как Text:: CSV или некоторые такие, которые вы можете добавить к shebang с помощью -M
.
-l
и -p
также являются вашими друзьями.
Если есть причина, вы не можете использовать простое решение, предоставленное ennuikiller выше, тогда вам придется использовать Typeglobs для управления файловыми дескрипторами. Это больше работает. В этом примере копируется из файла в $ARGV[0]
в файл $ARGV[1]
. По умолчанию это значения STDIN
и STDOUT
, если файлы не указаны.
use English;
my $in;
my $out;
if ($#ARGV >= 0){
unless (open($in, "<", $ARGV[0])){
die "could not open $ARGV[0] for reading.";
}
}
else {
$in = *STDIN;
}
if ($#ARGV >= 1){
unless (open($out, ">", $ARGV[1])){
die "could not open $ARGV[1] for writing.";
}
}
else {
$out = *STDOUT;
}
while ($_ = <$in>){
$out->print($_);
}
$ARGV[0]
т. Д. На другую переменную), где все остальные ответы потерпеть поражение...
unshift
имя файла на @ARGV
и используйте оператор diamond <>
.
Do
$userinput = <STDIN>; #read stdin and put it in $userinput
chomp ($userinput); #cut the return / line feed character
если вы хотите прочитать только одну строку
Бесстыдно украден из Neil Best и Рон
Предположим, что script name: stdinProcessor.pl
#!/usr/bin/perl
BEGIN: {
print "Doing some stuff first\n";
}
foreach $line ( <STDIN> ) {
chomp($line);
print "$line\n";
}
# Do something at the exit
print "Iteration done\n"
Пример:
$echo '1\n2\n3' | ./stdinProcessor.pl
Doing some stuff first
1
2
3
Iteration done
Вот как я создал script, который может принимать либо входы командной строки, либо перенаправлять текстовый файл.
if ($#ARGV < 1) {
@ARGV = ();
@ARGV = <>;
chomp(@ARGV);
}
Это переназначает содержимое файла на @ARGV, оттуда вы просто обрабатываете @ARGV, как если бы кто-то включал параметры командной строки.
ПРЕДУПРЕЖДЕНИЕ
Если файл не перенаправлен, программа будет сидеть в режиме ожидания, потому что ожидает ввода от STDIN.
Я не понял способ определить, перенаправляется ли файл, но для устранения проблемы с STDIN.
$#ARGV < 1
вместо (о чем я думаю) более ясного @ARGV == 1
?
if(my $file = shift) { # if file is specified, read from that
open(my $fh, '<', $file) or die($!);
while(my $line = <$fh>) {
print $line;
}
}
else { # otherwise, read from STDIN
print while(<>);
}
<>
автоматически найдет и прочитает любой файл (ы), указанный в командной строке. Там нет необходимости, if
.
shift
@ARGV = "/path/to/some/file.ext";
и он читает файл - так что вы даже можете запрограммировать файл по умолчанию при определенных условиях.