1

Perl を始めたばかりで、とても楽しんでいます。私はいくつかの基本的な関数を書いていますが、本当にできるようにしたいのは、コンソール コマンドを使用してそれらの関数をインテリジェントに使用することです。たとえば、2 つの数値を加算する関数があるとします。コンソールに「add 2, 4」と入力して最初の単語を読み取り、2 つの数字を「add」関数のパラメーターとして渡すことができるようにしたいと考えています。基本的に、Perl を使用して基本的なスクリプトを作成する際に助けを求めています ^^'.

VB でこれを行う方法について漠然としたアイデアはありますが、Perl では、どこから始めればよいか、どの関数が役立つかはわかりません。スカラーの内容を配列に分解できる VB.net の「Split」関数のようなものはありますか? たとえば、スカラーで一度に 1 つの単語を分析したり、区切り記号に到達するまでスカラーを反復処理したりする簡単な方法はありますか?

お役に立てば幸いです。ご意見をお待ちしております。私は専門家ではありません。数週間前に Perl を始めました。VB.net を始めてまだ半年です。

ありがとうございました!

編集:何を提案すればよいかわからず、役立つ可能性のある単純で直感的なリソースを知っている場合は、それもいただければ幸いです。

4

3 に答える 3

3

名前でコマンドにディスパッチするスクリプトを作成するのはかなり簡単です。簡単な例を次に示します。

#!/usr/bin/env perl

use strict;
use warnings;

# take the command name off the @ARGV stack
my $command_name = shift;

# get a reference to the subroutine by name
my $command = __PACKAGE__->can($command_name) || die "Unknown command: $command_name\n";

# execute the command, using the rest of @ARGV as arguments
# and print the return with a trailing newline
print $command->(@ARGV);
print "\n";

sub add {
  my ($x, $y) = @_;
  return $x + $y;
}

sub subtract {
  my ($x, $y) = @_;
  return $x - $y;
}

このスクリプト (という名前のmyscript.pl) は、次のように呼び出すことができます

$ ./myscript.pl add 2 3

また

$ ./myscript.pl subtract 2 3

しばらくそれを試してみると、さらに進んで、この種のフレームワークを使用したくなるかもしれません。App::Cmdのようないくつかの利用可能なものがあります。または、上に示したロジックを使用して、必要に応じてモジュール化することもできます。

于 2013-03-12T21:41:35.547 に答える
1

以下は、単純なスクリプト言語の短い実装です。

各ステートメントの長さは正確に 1 行で、次のような構造になっています。

Statement = [<Var> =] <Command> [<Arg> ...]
# This is a regular grammar, so we don't need a complicated parser.

トークンは空白で区切られます。コマンドは、任意の数の引数を取ることができます。これらは、変数の内容$var、文字列"foo"、または数値 (int または float) のいずれかです。

これらは Perl のスカラーであるため、文字列と数値の間に目に見える違いはありません。

スクリプトのプリアンブルは次のとおりです。

#!/usr/bin/perl
use strict;
use warnings;
use 5.010;

strictwarningsこれらは Perl を学習する際に不可欠です。はuse 5.010最小バージョンであり、sayビルトインも定義します (a と同様ですprintが、改行を追加します)。

ここで、2 つのグローバル変数を宣言します。%envハッシュ (テーブルまたは辞書) は、変数名をその値に関連付けます。%functions組み込み関数を保持します。値は無名関数です。

my %env;

my %functions = (
  add => sub { $_[0] + $_[1] },
  mul => sub { $_[0] * $_[1] },
  say => sub { say $_[0] },
  bye => sub { exit 0 },
);

次に、read-eval-loop を実行します (デフォルトでは出力しません)。readline 演算子<>は、最初のコマンド ライン引数として指定されたファイルから読み取るか、ファイル名が指定されていない場合は STDIN から読み取ります。

while (<>) {
  next if /^\s*\#/; # jump comment lines
  # parse the line. We get a destination $var, a $command, and any number of @args
  my ($var, $command, @args) = parse($_);
  # Execute the anonymous sub specified by $command with the @args
  my $value = $functions{ $command }->(@args);
  # Store the return value if a destination $var was specified
  $env{ $var } = $value if defined $var;
}

それはかなり些細なことでした。次に、解析コードをいくつか示します。Perl は、正規表現を演算子で文字列に「バインド」します=~/foo/正規表現はまたはのようになりますm/foo/。フラグを使用すると、/x正規表現に実際の空白と一致しない空白を含めることができます。フラグは/gグローバルに一致します。これにより、\Gアサーションも有効になります。これは、最後に成功したマッチが終了した場所です。/cフラグは、このスタイルの解析で一度に 1 つの一致を消費し、出力文字列内の正規表現エンジンの位置がリセットされるのを防ぐために重要ですm//gc

sub parse {
  my ($line) = @_; # get the $line, which is a argument
  my ($var, $command, @args); # declare variables to be filled

  # Test if this statement has a variable declaration
  if ($line =~ m/\G\s* \$(\w+) \s*=\s* /xgc) {
    $var = $1; # assign first capture if successful
  }

  # Parse the function of this statement.
  if ($line =~ m/\G\s* (\w+) \s*/xgc) {
    $command = $1;
    # Test if the specified function exists in our %functions
    if (not exists $functions{$command}) {
      die "The command $command is not known\n";
    }
  } else {
    die "Command required\n"; # Throw fatal exception on parse error.
  }

  # As long as our matches haven't consumed the whole string...
  while (pos($line) < length($line)) {
    # Try to match variables
    if ($line =~ m/\G \$(\w+) \s*/xgc) {
      die "The variable $1 does not exist\n" if not exists $env{$1};
      push @args, $env{$1};
    }
    # Try to match strings
    elsif ($line =~ m/\G "([^"]+)" \s*/xgc) {
      push @args, $1;
    }
    # Try to match ints or floats
    elsif ($line =~ m/\G (\d+ (?:\.\d+)? ) \s*/xgc) {
      push @args, 0+$1;
    }
    # Throw error if nothing matched
    else {
      die "Didn't understand that line\n";
    }
  }
  # return our -- now filled -- vars.
  return $var, $command, @args;
}

Perl 配列は連結リストのように扱うことができます:shift最初の要素を削除して返します (pop最後の要素に対しても同じことを行います)。要素を末尾、先頭pushに追加します。unshift

ほとんどのプログラミング言語は、次のような単純なプログラムを実行できます。

#!my_little_language
$a = mul 2 20
$b = add 0 2
$answer = add $a $b
say $answer
bye

(1) Perl スクリプトが に保存されmy_little_language、実行可能に設定され、システム PATH にあり、(2) 上記の小さな言語のファイルが として保存されmeaning_of_life.mll、実行可能に設定されている場合、

$ ./meaning_of_life

実行できるはずです。

出力は明らかに42. 私たちの言語にはまだ文字列操作や変数への単純な代入がないことに注意してください。また、他の関数の戻り値で直接関数を呼び出せるといいですね。これには、ある種のかっこまたは優先メカニズムが必要です。また、この言語では、バッチ処理 (既にサポートされています) のエラー報告を改善する必要があります。

于 2013-03-12T20:34:52.090 に答える
1

コマンドライン引数を解析したい。Aspaceは区切り文字として機能するため、次の./add.pl 2 3ようなことを行うだけです。

$num1=$ARGV[0];
$num2=$ARGV[1];

print $num1 + $num2;

印刷します5

于 2013-03-12T18:13:57.860 に答える