الوصول إلى عامل الزاوية الفارغة "<>" لـ Perl من مقبض ملف فعلي؟

StackOverflow https://stackoverflow.com/questions/1640986

سؤال

أحب استخدام ميزة Perl الأنيقة حيث القراءة من عامل الزاوية الفارغة <> يمنح برنامجك دلالات مرشح UNIX بطريقة سحرية، ولكنني أود أن أكون قادرًا على الوصول إلى هذه الميزة من خلال مقبض ملف فعلي (أو IO::مقبض كائن، أو ما شابه)، حتى أتمكن من القيام بأشياء مثل تمريره إلى الإجراءات الفرعية وما شابه.هل هناك أي طريقة للقيام بذلك؟

هذا السؤال صعب بشكل خاص على Google، لأن البحث عن "مشغل الزاوية" و"مقبض الملف" يخبرني فقط بكيفية القراءة من مقابض الملفات باستخدام عامل الزاوية.

هل كانت مفيدة؟

المحلول

من perldoc perlvar:

  • ARGV

مقبض الملف الخاص الذي يتكرر عبر أسماء ملفات سطر الأوامر في @ARGV.تتم كتابته عادةً كمقبض ملف فارغ في عامل الزاوية <>.لاحظ ذلك حاليا ARGV له تأثيره السحري فقط داخل <> المشغل أو العامل؛في مكان آخر، يكون مجرد مقبض ملف عادي يتوافق مع آخر ملف تم فتحه بواسطة <>.على وجه الخصوص، عابرة \*ARGV كمعلمة لوظيفة تتوقع أن مقبض الملف قد لا يتسبب في قيام وظيفتك بقراءة محتويات جميع الملفات الموجودة تلقائيًا @ARGV.

أعتقد أن هذا يجيب على جميع جوانب سؤالك بهذه الطريقة "أكره أن أقول ذلك ولكنه لن يفعل ما تريد".ما يمكنك فعله هو إنشاء وظائف تتطلب قائمة بأسماء الملفات لفتحها، وقم بذلك:

sub takes_filenames (@) {
  local @ARGV = @_;
  // do stuff with <>
}

ولكن ربما يكون هذا هو أفضل ما يمكنك إدارته.

نصائح أخرى

والتوسع في فكرة كريس وتز، وهنا هو تطبيق بدائية جدا:

#!/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]:

ويبدو قد تم تنفيذه بالفعل ك <لأ href = "http://search.cpan.org/~jv/Iterator-Diamond-0.03/lib/Iterator/Diamond.pm" يختلط = "نوفولو noreferrer" هذا > Iterator::Diamond . أيضا تعطيل مكرر :: الماس السحر 2-حجة-المفتوح الذي يستخدم بيرل عند قراءة <ARGV>. حتى أفضل، فإنه يدعم '-' القراءة كما STDIN، دون تمكين كل السحر الآخرين. في الواقع، وأنا قد استخدامه لهذا الغرض فقط على صورة واحدة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top