Как я реализую таблицы отправки в Perl?

В то время как более поздние версии Windows имеют where команда, можно также сделать это с Windows XP при помощи модификаторов переменной среды, следующим образом:

c:\> for %i in (cmd.exe) do @echo.   %~$PATH:i
   C:\WINDOWS\system32\cmd.exe

c:\> for %i in (python.exe) do @echo.   %~$PATH:i
   C:\Python25\python.exe

Вам не нужны никакие дополнительные инструменты, и это не ограничено PATH, так как можно заменить любой переменной среды (в формате пути, конечно), что Вы хотите использовать.

<час>

И, если Вы хотите тот, который может обработать все расширения в PATHEXT (поскольку сам Windows делает), этот добивается цели:

@echo off
setlocal enableextensions enabledelayedexpansion

:: Needs an argument.

if "x%1"=="x" (
    echo Usage: which ^<progName^>
    goto :end
)

:: First try the unadorned filenmame.

set fullspec=
call :find_it %1

:: Then try all adorned filenames in order.

set mypathext=!pathext!
:loop1
    :: Stop if found or out of extensions.

    if "x!mypathext!"=="x" goto :loop1end

    :: Get the next extension and try it.

    for /f "delims=;" %%j in ("!mypathext!") do set myext=%%j
    call :find_it %1!myext!

:: Remove the extension (not overly efficient but it works).

:loop2
    if not "x!myext!"=="x" (
        set myext=!myext:~1!
        set mypathext=!mypathext:~1!
        goto :loop2
    )
    if not "x!mypathext!"=="x" set mypathext=!mypathext:~1!

    goto :loop1
:loop1end

:end
endlocal
goto :eof

:: Function to find and print a file in the path.

:find_it
    for %%i in (%1) do set fullspec=%%~$PATH:i
    if not "x!fullspec!"=="x" @echo.   !fullspec!
    goto :eof

Это на самом деле возвращает все возможности, но можно настроить его довольно легко для определенных поисковых правил.

5
задан Sinan Ünür 15 August 2009 в 14:07
поделиться

7 ответов

Во-первых, проверка равенства строк в Perl - это eq , а не == .

Если у вас есть методы для выполнения работы, скажем, с именем bit и ftp,

my %proc = (
    bit => \&bit,
    ftp => \&ftp,
);

my $proc = $proc{$trans_type};
$proc->() if defined $proc;
13
ответ дан 18 December 2019 в 05:31
поделиться

Вы можете использовать для этого хеш ...

  1. Пусть каждый метод передачи регистрирует себя в хеше. $ MyApp :: TransferManager :: МЕТОДЫ {ftp} = \ & do_ftp; sub do_ftp {...} 1;

  2. Каждый метод передачи использует согласованный API. Может быть, это просто функция, или это может быть интерфейс объекта.

  3. Вызов передачи через хэш.

     sub do_transfer {
     # ...
     мой $ sub = $ MyApp :: TransferManager :: МЕТОДЫ {$ метод}
     или квакать "Неизвестный метод передачи $ method";
     $ sub -> ($ arg1, $ arg2, ...);
     # ...
    }
    

Кстати: метод регистрации OO будет выглядеть примерно так:

package MyApp::TransferManager;
use Carp;
use strict;

my %registered_method;

sub register {
    my ($class, $method, $sub) = @_;

    exists $registered_method{$method}
        and croak "method $method already registered";

    $registered_method{$method} = $sub;
}

# ...

1;

(Ни один из этих кодов не протестирован; прошу прощения за пропущенные точки с запятой)

8
ответ дан 18 December 2019 в 05:31
поделиться

Правильная конструкция здесь - завод. Посмотрите, как с этим справляется DBI . В итоге вы получите класс TransferAgent , который создает один из любого количества классов TransferAgent :: * . Очевидно, вам понадобится больше проверок ошибок, чем предоставляет реализация ниже. Использование подобной фабрики означает, что вы можете добавлять новые типы агентов передачи без необходимости добавлять или изменять какой-либо код.

TransferAgent.pm - фабричный класс:

package TransferAgent;

use strict;
use warnings;

sub connect {
    my ($class, %args) = @_;

    require "$class/$args{type}.pm";

    my $ta = "${class}::$args{type}"->new(%args);
    return $ta->connect;
}

1;

TransferAgent / Base.pm - содержит базу функциональность класса TransferAgent :: * :

package TransferAgent::Base;

use strict;
use warnings;

use Carp;

sub new {
    my ($class, %self) = @_;
    $self{_files_transferred} = [];
    $self{_bytes_transferred} = 0;
    return bless \%self, $class;
}

sub files_sent { 
    return wantarray ?  @{$_[0]->{_files_sent}} : 
        scalar @{$_[0]->{_files_sent}};
}

sub files_received { 
    return wantarray ?  @{$_[0]->{_files_recv}} : 
        scalar @{$_[0]->{_files_recv}};
}

sub cwd    { return $_[0]->{_cwd}       }
sub status { return $_[0]->{_connected} }

sub _subname {
    return +(split "::", (caller 1)[3])[-1];
}

sub connect    { croak _subname, " is not implemented by ", ref $_[0] }
sub disconnect { croak _subname, " is not implemented by ", ref $_[0] }
sub chdir      { croak _subname, " is not implemented by ", ref $_[0] }
sub mode       { croak _subname, " is not implemented by ", ref $_[0] }
sub put        { croak _subname, " is not implemented by ", ref $_[0] }
sub get        { croak _subname, " is not implemented by ", ref $_[0] }
sub list       { croak _subname, " is not implemented by ", ref $_[0] }

1;

TransferAgent / FTP.pm - реализует (фиктивный) FTP-клиент:

package TransferAgent::FTP;

use strict;
use warnings;

use Carp;

use base "TransferAgent::Base";

our %modes = map { $_ => 1 } qw/ascii binary ebcdic/;

sub new {
    my $class = shift;
    my $self  = $class->SUPER::new(@_);
    $self->{_mode} = "ascii";
    return $self;
}

sub connect    { 
    my $self = shift;
    #pretend to connect
    $self->{_connected} = 1;
    return $self;
}

sub disconnect {
    my $self = shift;
    #pretend to disconnect
    $self->{_connected} = 0;
    return $self;
}

sub chdir { 
    my $self = shift;
    #pretend to chdir
    $self->{_cwd} = shift;
    return $self;
}

sub mode {
    my ($self, $mode) = @_;

    if (defined $mode) {
        croak "'$mode' is not a valid mode"
            unless exists $modes{$mode};
        #pretend to change mode
        $self->{_mode} = $mode;
        return $self;
    }

    #return current mode
    return $self->{_mode};
}

sub put {
    my ($self, $file) = @_;
    #pretend to put file
    push @{$self->{_files_sent}}, $file;
    return $self;
}

sub get {
    my ($self, $file) = @_;
    #pretend to get file
    push @{$self->{_files_recv}}, $file;
    return $self;
}

sub list {
    my $self = shift;
    #pretend to list remote files
    return qw/foo bar baz quux/;
}

1;

script.pl - как использовать TransferAgent:

#!/usr/bin/perl

use strict;
use warnings;

use TransferAgent;

my $ta = TransferAgent->connect(
    type     => "FTP",
    host     => "foo",
    user     => "bar",
    password => "baz",
);

print "files to get: ", join(", ", $ta->list), "\n";
for my $file ($ta->list) {
    $ta->get($file);
}
print "files gotten: ", join(", ", $ta->files_received), "\n";

$ta->disconnect;
6
ответ дан 18 December 2019 в 05:31
поделиться

I have several examples in Mastering Perl in the sections on dynamic subroutines.

3
ответ дан 18 December 2019 в 05:31
поделиться

OO было бы излишним. Мое решение, вероятно, будет выглядеть примерно так:

sub ftp_transfer { ... }
sub bit_transfer { ... }
my $transfer_sub = { 'ftp' => \&ftp_transfer, 'bit' => \&bit_transfer, ... };
...
sub upload_file {
    my ($file, ...) = @_;
    ...
    $transfer_sub->{$file->{trans_type}}->(...);
}
1
ответ дан 18 December 2019 в 05:31
поделиться

Вы сказали, что сначала он будет использовать FTP, а позже перейдет к другим методам передачи. Я бы не стал называть «элегантным», пока вам действительно не понадобится добавить вторую или третью технологию. Этот второй метод передачи может никогда не потребоваться. : -)

Если вы хотите сделать это как «научный проект», тогда отлично.

Я устал видеть объектно-ориентированные шаблоны проектирования, усложняющие решения проблем, которые никогда не возникают.

Оберните первый метод передачи в метод uploadFile. Добавьте if, то else для второго метода. Получите элегантность и проведите рефакторинг третьего метода. К тому времени у вас будет достаточно примеров, так что ваше решение, вероятно, будет довольно общим.

Конечно, я хочу сказать, что второй и третий методы могут никогда не потребоваться.

1
ответ дан 18 December 2019 в 05:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: