我刚开始在Perl工作,我很享受它。我正在编写一些基本函数,但我真正希望能够使用控制台命令智能地使用这些函数。例如,假设我有一个添加两个数字的函数。我希望能够键入控制台“添加2,4”并读取第一个单词,然后将这两个数字作为参数传递给“添加”功能。基本上,我在使用Perl ^^'创建一些基本脚本时请求帮助。
我对如何在VB中执行此操作有一些模糊的想法,但Perl,我不知道我从哪里开始,或者哪些函数对我有用。是否有像VB.net的“拆分”功能,你可以将标量的内容分解为数组?有没有一种简单的方法可以在标量中一次分析一个单词,或者通过标量迭代直到你碰到一个分隔符,例如?
我希望你能提供帮助,任何建议都表示赞赏!请记住,我不是专家,我几周前就开始使用Perl,而且我只用了半年的VB.net。
谢谢!
编辑:如果您不确定建议什么,并且您知道任何可能有帮助的简单/直观资源,那么也将不胜感激。
答案 0 :(得分: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,或者您可以采用上面显示的逻辑并按您认为合适的方式进行模块化。
答案 1 :(得分:1)
您想要解析命令行参数。 space
作为分隔符,所以只需执行./add.pl 2 3
这样的事情:
$num1=$ARGV[0];
$num2=$ARGV[1];
print $num1 + $num2;
将打印5
答案 2 :(得分: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;
学习Perl时, strict
和warnings
是必不可少的,否则太多奇怪的东西都是可能的。 use 5.010
是最低版本,它还定义say
内置版(如print
,但附加换行符。)
现在我们声明两个全局变量:%env
哈希(table或dict)将变量名称与其值相关联。 %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
标志对于此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
。请注意,我们的语言还没有字符串操作或简单的变量赋值。此外,能够直接调用具有其他函数返回值的函数会很好。这需要某种parens或优先机制。此外,该语言需要更好的错误报告批处理(它已经支持)。