6

問題は、n 個のコマンド ライン引数があることです。常に少なくとも 2 つ存在しますが、最大数には制限がありません。最初の引数は操作モードを指定し、2 番目の引数は処理するファイルです。3 番目から n 番目までは、ファイルに対して行うことです (2 つの引数を渡すだけで、ユーザーがファイルをきれいにしたいだけかもしれないので、何もないかもしれません)。

配列を操作するために Perl で使用できるメソッドを調べていますが、アイテム 3 から配列の最後まで反復する "Perlish" の方法が何であるかがわかりません。

私が見たいくつかのオプション:

  • 「-」で始まらない要素が見つかるまで、配列の最後からポップします(ファイルパスが「-」で始まらないため、問題が発生する可能性があると思いますが)。
  • 配列を 2 回シフトして、最初の 2 つの要素を削除します。残っているものは何でも、サイズが少なくとも 1 であれば、繰り返し処理できます。

2 番目のオプションが気に入っていますが、それが Perlish かどうかはわかりません。私は Perl を学ぼうとしているので、Perl で物事を行うための正しい方法を学ぶこともできます。

4

8 に答える 8

17

Sinan が書いたように Getopt モジュールを使用する以外に、私はおそらく次のものを使用します。

my ( $operation, $file, @things ) = @ARGV;

そして、次のことができます。

for my $thing_to_do ( @things ) {
...
}
于 2009-10-05T15:59:18.073 に答える
12

私見、必要なことを達成するPerlishの方法は、CPAN の Getopt モジュールの1つを使用することです。

それでも手動で行いたい場合は、2 番目のオプションを使用します (これは、メソッド呼び出しの最初の引数を処理する方法に似ています)。

die "Must provide filename and operation\n" unless @ARGV >= 2;

my $op = shift @ARGV;
my $file = shift @ARGV;

if ( @ARGV ) {
    # handle the other arguments;
}
于 2009-10-05T15:57:19.497 に答える
9

コマンドライン引数の解析にはGetopt::Longを使用することを強くお勧めします。これは標準モジュールであり、素晴らしく機能し、まさにあなたがやろうとしていることを簡単にします。

use strict;
use warnings;
use Getopt::Long;

my $first_option = undef;
my $second_option = undef;

GetOptions ('first-option=s' => \$first_option, 
            'second-option=s' => \$second_option);

die "Didn't pass in first-option, must be xxxyyyzzz."
    if ! defined $first_option;
die "Didn't pass in second-option, must be aaabbbccc."
    if ! defined $second_option;

foreach my $arg (@ARGV) {
    ...
}

これにより、長いオプション名を使用できるようになり、情報が変数に自動的に入力され、テストできるようになります。「version」オプションや「help」オプションを追加するなど、引数の特別な解析を行うことなく、後でコマンドを追加することもできます。

# adding these to the above example...
my $VERSION = '1.000';
sub print_help { ... }

# ...and replacing the previous GetOptions with this...
GetOptions ('first-option=s' => \$first_option, 
            'second-option=s' => \$second_option)
            'version' => sub { print "Running version $VERSION"; exit 1 },
            'help' => sub { print_help(); exit 2 } );

-次に、コマンド ラインで--, 、最初の文字、またはオプション全体を使用して呼び出すことができ、GetOptionsすべてを把握できます。これにより、プログラムがより堅牢になり、理解しやすくなります。それはあなたが言うことができるより「推測可能」です。@ARGV最良の部分は、を処理するコードを変更する必要がないことGetOptionsです。

于 2009-10-05T16:25:46.990 に答える
7

Perl で物事を行う最も標準的な方法は、CPAN を使用することです。

したがって、私の最初の選択はGetopt::Longです。DevShed に関するチュートリアルもあります: Processing Command Line Options with Perl

于 2009-10-05T15:59:35.687 に答える
6

スライスを使用して2番目を抽出できます。たとえば、次のようにします。

[dsm@localhost:~]$ perl -le 'print join ", ", @ARGV[2..$#ARGV];' 1 2 3 4 5 6 7 8 9 10 00
3, 4, 5, 6, 7, 8, 9, 10, 00
[dsm@localhost:~]$ 

ただし、おそらく使用する必要がありますshift(またはさらに良いGetOpt::Long

于 2009-10-05T16:00:02.067 に答える
3

deepesz の回答は、良い方法の 1 つです。

2番目のオプションにも問題はありません:

my $op     = shift; # implicit shift from @ARGV
my $file   = shift; 
my @things = @ARGV;

# iterate over @things;

@ARGVコピーをスキップして@things、直接作業することもできます。ただし、スクリプトが非常に短く、非常に単純で、時間の経過とともに複雑になる可能性が低い場合を除き、近道をしすぎることは避けます。

deepesz のアプローチを選択するか、これを選択するかは、主に好みの問題です。

どちらが優れているかを決定することは、実際には哲学の問題です。問題の核心は、 のようなグローバルを変更する必要があるかどうかです@ARGV。目立つ方法で行われている限り、大したことではないと言う人もいます。他の人は、そのままにしておくことを支持すると主張するでしょう@ARGV

速度やメモリの問題のために、どちらか一方のオプションを支持する人がいることに注意してください。配列はほとんどの@ARGVシェルで非常に小さいサイズに制限されているため、1 つの方法を使用しても他の方法よりも大幅に最適化することはできません。

前述のGetopt::Longも優れた選択肢です。

于 2009-10-05T16:28:41.370 に答える
3

MooseX::Getoptを見てください。Moosey ! .

MooseX::Getopt の例:

# getopt.pl

{
    package MyOptions;
    use Moose;
    with 'MooseX::Getopt';

    has oper   => ( is => 'rw', isa => 'Int', documentation => 'op doc stuff' );
    has file   => ( is => 'rw', isa => 'Str', documentation => 'about file' );
    has things => ( is => 'rw', isa => 'ArrayRef', default => sub {[]} );

    no Moose;
}

my $app = MyOptions->new_with_options;

for my $thing (@{ $app->things }) {
    print $app->file, " : ", $thing, "\n";
}

# => file.txt : item1
# => file.txt : item2
# => file.txt : item3

次のように実行すると、上記が生成されます。

perl getopt.pl --oper 1 --file file.txt --things item1 --things item2 --things item3


これらの Moose タイプがチェックされます... ./getopt --oper "not a number"生成されます:

オプション oper の値「非数値」は無効です (数値が必要です)

そして無料で、いつでも使用リストを取得できます;-)

使用法: getopt.pl [長いオプション...]
         --file ファイルについて少し
         --oper op doc スタッフ
         - もの    

/I3az/

于 2009-10-05T18:17:02.290 に答える
0

より一般的な配列の場合:

for(my $i=2; $i<@array; $i++) {
    print "$array[$i]\n";
}

これは、3 番目の要素 (インデックス 2) から開始して、配列をループ処理します。明らかに、あなたが指定した特定の例では、depeszの答えが最も簡単で最高です。

于 2009-10-06T15:30:42.990 に答える