실제 파일 핸들에서 Perl의 빈 각 "<>"연산자에 대한 액세스?
-
08-07-2019 - |
문제
나는 빈 앵글 연산자의 독서가있는 Nifty Perl 기능을 사용하고 싶습니다. <>
마술처럼 프로그램 UNIX 필터 의미론을 제공하지만 실제 파일 핸들 (또는 io :: 핸들 객체 또는 이와 유사한), 서브 루틴 등으로 전달하는 것과 같은 일을 할 수 있습니다. 이것을 할 방법이 있습니까?
"앵글 연산자"와 "파일 핸들"을 검색하면 앵글 연산자를 사용하여 파일 핸들에서 읽는 방법을 알려주기 때문에이 질문은 특히 Google이 어렵습니다.
해결책
에서 perldoc perlvar
:
ARGV
명령 줄 파일 이름을 반복하는 특수 파일 핸들
@ARGV
. 일반적으로 각도 연산자의 NULL 파일 핸들로 작성되었습니다.<>
. 현재 주목하십시오ARGV
내에서만 마법 효과가 있습니다<>
운영자; 다른 곳에서는 열린 마지막 파일에 해당하는 일반 파일 핸들입니다.<>
. 특히 통과\*ARGV
파일 핸들을 기대하는 함수의 매개 변수로서 기능이 모든 파일의 내용을 자동으로 읽지 않을 수 있습니다.@ARGV
.
나는 당신의 질문의 모든 측면에 "그것을 말하기를 싫어하지만 당신이 원하는 것을 할 수는 없다"고 생각합니다. 당신이 할 수있는 일은 파일 이름 목록을 열고 다음을 수행하는 기능을 만드는 것입니다.
sub takes_filenames (@) {
local @ARGV = @_;
// do stuff with <>
}
그러나 그것은 아마도 당신이 관리 할 수있는 최고 일 것입니다.
다른 팁
Chris Lutz의 아이디어를 확장하면서 매우 기본적인 구현이 있습니다.
#!/usr/bin/perl
package My::ARGV::Reader;
use strict; use warnings;
use autodie;
use IO::Handle;
use overload
'<>' => \&reader,
'""' => \&argv,
'0+' => \&input_line_number,
;
sub new {
my $class = shift;
my $self = {
names => [ @_ ],
handles => [],
current_file => 0,
};
bless $self => $class;
}
sub reader {
my $self = shift;
return scalar <STDIN> unless @{ $self->{names}};
my $line;
while ( 1 ) {
my $current = $self->{current_file};
return if $current >= @{ $self->{names} };
my $fh = $self->{handles}->[$current];
unless ( $fh ) {
$self->{handles}->[$current] = $fh = $self->open_file;
}
if( eof $fh ) {
close $fh;
$self->{current_file} = $current + 1;
next;
}
$line = <$fh>;
last;
}
return $line;
}
sub open_file {
my $self = shift;
my $name = $self->{names}->[ $self->{current_file} ];
open my $fh, '<', $name;
return $fh;
}
sub argv {
my $self = shift;
my $name = @{$self->{names}}
? $self->{names}->[ $self->{current_file} ]
: '-'
;
return $name;
}
sub input_line_number {
my $self = shift;
my $fh = @{$self->{names}}
? $self->{handles}->[$self->{current_file}]
: \*STDIN
;
return $fh->input_line_number;
}
다음과 같이 사용할 수 있습니다.
package main;
use strict; use warnings;
my $it = My::ARGV::Reader->new(@ARGV);
echo($it);
sub echo {
my ($it) = @_;
printf "[%s:%d]:%s", $it, +$it, $_ while <$it>;
}
산출:
[file1:1]:bye bye [file1:2]:hello [file1:3]:thank you [file1:4]:no translation [file1:5]: [file2:1]:chao [file2:2]:hola [file2:3]:gracias [file2:4]:
이것은 이미 구현 된 것 같습니다 Iterator::Diamond
. 반복자 :: 다이아몬드는 또한 판독 할 때 Perl이 사용하는 2- 연락 마법을 비활성화합니다. <ARGV>
. 더 좋은 점은 독서를 지원합니다 '-'
Stdin으로서 다른 모든 마법을 가능하게하지 않습니다. 사실, 나는 단일 파일에서만 그 목적으로 사용할 수 있습니다.