我如何在 Raku(以前称为 Perl 6)中解析和验证命令行参数?
How do I parse and validate command line arguments in Raku (formerly known as Perl 6)?
在 Perl 5 中,我可以使用 Getopt::Long
来解析命令行参数并进行一些验证(见下文来自 http://perldoc.perl.org/Getopt/Long.html)。
use Getopt::Long;
my $data = "file.dat";
my $length = 24;
my $verbose;
GetOptions ("length=i" => $length, # numeric
"file=s" => $data, # string
"verbose" => $verbose) # flag
or die("Error in command line arguments\n");
say $length;
say $data;
say $verbose;
此处 =i
in "length=i"
对与 --length
关联的值创建数字类型约束,而 "file=s"
中的 =s
创建类似的字符串类型约束.
如何在 Raku(née Perl 6)中做类似的事情?
基础知识
该功能内置于 Raku(以前称为 Perl 6)中。这是您在 Raku 中的 Getopt::Long
代码的等价物:
sub MAIN ( Str :$file = "file.dat"
, Num :$length = Num(24)
, Bool :$verbose = False
)
{
$file.say;
$length.say;
$verbose.say;
}
MAIN
是一个特殊的子程序,它根据其签名自动解析命令行参数。
Str
和 Num
提供字符串和数字类型约束。
Bool
使 $verbose
成为二进制标志,如果不存在或称为 --/verbose
,则为 False
。 (--/foo
中的/
是a common Unix command line syntax for setting an argument to False
)。
:
附加在子例程签名中的变量前,使它们成为命名(而不是位置)参数。
默认值是使用 $variable =
后跟默认值提供的。
别名
如果你想要单个字符或其他别名,你可以使用 :f(:$foo)
语法。
sub MAIN ( Str :f(:$file) = "file.dat"
, Num :l(:$length) = Num(24)
, Bool :v(:$verbose) = False
)
{
$file.say;
$length.say;
$verbose.say;
}
:x(:$smth)
为 --smth
添加别名,例如本例中的短别名 -x
。多个别名和全名也可用,这里是一个例子::foo(:x(:bar(:y(:$baz))))
将得到 --foo
、-x
、--bar
、-y
和 --baz
如果其中任何一个将传递给 $baz
.
位置参数(和示例)
MAIN
也可以与位置参数一起使用。例如,这里是 Guess the number (from Rosetta Code). It defaults to a min of 0 and max of 100, but any min and max number could be entered. Using is copy
允许在子程序内更改参数:
#!/bin/env perl6
multi MAIN
#= Guessing game (defaults: min=0 and max=100)
{
MAIN(0, 100)
}
multi MAIN ( $max )
#= Guessing game (min defaults to 0)
{
MAIN(0, $max)
}
multi MAIN
#= Guessing game
( $min is copy #= minimum of range of numbers to guess
, $max is copy #= maximum of range of numbers to guess
)
{
#swap min and max if min is lower
if $min > $max { ($min, $max) = ($max, $min) }
say "Think of a number between $min and $max and I'll guess it!";
while $min <= $max {
my $guess = (($max + $min)/2).floor;
given lc prompt "My guess is $guess. Is your number higher, lower or equal (or quit)? (h/l/e/q)" {
when /^e/ { say "I knew it!"; exit }
when /^h/ { $min = $guess + 1 }
when /^l/ { $max = $guess }
when /^q/ { say "quiting"; exit }
default { say "WHAT!?!?!" }
}
}
say "How can your number be both higher and lower than $max?!?!?";
}
使用信息
此外,如果您的命令行参数与 MAIN
签名不匹配,默认情况下您会收到一条有用的用法消息。请注意以 #=
开头的子例程和参数注释如何巧妙地合并到此用法消息中:
./guess --help
Usage:
./guess -- Guessing game (defaults: min=0 and max=100)
./guess <max> -- Guessing game (min defaults to 0)
./guess <min> <max> -- Guessing game
<min> minimum of range of numbers to guess
<max> maximum of range of numbers to guess
此处--help
不是定义的命令行参数,因此触发此用法消息。
另见
另见 2010, 2014, and 2018 Perl 6 advent calendar posts on MAIN
, the post Parsing command line arguments in Perl 6, and the section of Synopsis 6 about MAIN。
另外,perl6 也有 Getopt::Long。您的程序几乎无需修改即可在其中运行:
use Getopt::Long;
my $data = "file.dat";
my $length = 24;
my $verbose;
get-options("length=i" => $length, # numeric
"file=s" => $data, # string
"verbose" => $verbose); # flag
say $length;
say $data;
say $verbose;
在 Perl 5 中,我可以使用 Getopt::Long
来解析命令行参数并进行一些验证(见下文来自 http://perldoc.perl.org/Getopt/Long.html)。
use Getopt::Long;
my $data = "file.dat";
my $length = 24;
my $verbose;
GetOptions ("length=i" => $length, # numeric
"file=s" => $data, # string
"verbose" => $verbose) # flag
or die("Error in command line arguments\n");
say $length;
say $data;
say $verbose;
此处 =i
in "length=i"
对与 --length
关联的值创建数字类型约束,而 "file=s"
中的 =s
创建类似的字符串类型约束.
如何在 Raku(née Perl 6)中做类似的事情?
基础知识
该功能内置于 Raku(以前称为 Perl 6)中。这是您在 Raku 中的 Getopt::Long
代码的等价物:
sub MAIN ( Str :$file = "file.dat"
, Num :$length = Num(24)
, Bool :$verbose = False
)
{
$file.say;
$length.say;
$verbose.say;
}
MAIN
是一个特殊的子程序,它根据其签名自动解析命令行参数。
Str
和 Num
提供字符串和数字类型约束。
Bool
使 $verbose
成为二进制标志,如果不存在或称为 --/verbose
,则为 False
。 (--/foo
中的/
是a common Unix command line syntax for setting an argument to False
)。
:
附加在子例程签名中的变量前,使它们成为命名(而不是位置)参数。
默认值是使用 $variable =
后跟默认值提供的。
别名
如果你想要单个字符或其他别名,你可以使用 :f(:$foo)
语法。
sub MAIN ( Str :f(:$file) = "file.dat"
, Num :l(:$length) = Num(24)
, Bool :v(:$verbose) = False
)
{
$file.say;
$length.say;
$verbose.say;
}
:x(:$smth)
为 --smth
添加别名,例如本例中的短别名 -x
。多个别名和全名也可用,这里是一个例子::foo(:x(:bar(:y(:$baz))))
将得到 --foo
、-x
、--bar
、-y
和 --baz
如果其中任何一个将传递给 $baz
.
位置参数(和示例)
MAIN
也可以与位置参数一起使用。例如,这里是 Guess the number (from Rosetta Code). It defaults to a min of 0 and max of 100, but any min and max number could be entered. Using is copy
允许在子程序内更改参数:
#!/bin/env perl6
multi MAIN
#= Guessing game (defaults: min=0 and max=100)
{
MAIN(0, 100)
}
multi MAIN ( $max )
#= Guessing game (min defaults to 0)
{
MAIN(0, $max)
}
multi MAIN
#= Guessing game
( $min is copy #= minimum of range of numbers to guess
, $max is copy #= maximum of range of numbers to guess
)
{
#swap min and max if min is lower
if $min > $max { ($min, $max) = ($max, $min) }
say "Think of a number between $min and $max and I'll guess it!";
while $min <= $max {
my $guess = (($max + $min)/2).floor;
given lc prompt "My guess is $guess. Is your number higher, lower or equal (or quit)? (h/l/e/q)" {
when /^e/ { say "I knew it!"; exit }
when /^h/ { $min = $guess + 1 }
when /^l/ { $max = $guess }
when /^q/ { say "quiting"; exit }
default { say "WHAT!?!?!" }
}
}
say "How can your number be both higher and lower than $max?!?!?";
}
使用信息
此外,如果您的命令行参数与 MAIN
签名不匹配,默认情况下您会收到一条有用的用法消息。请注意以 #=
开头的子例程和参数注释如何巧妙地合并到此用法消息中:
./guess --help
Usage:
./guess -- Guessing game (defaults: min=0 and max=100)
./guess <max> -- Guessing game (min defaults to 0)
./guess <min> <max> -- Guessing game
<min> minimum of range of numbers to guess
<max> maximum of range of numbers to guess
此处--help
不是定义的命令行参数,因此触发此用法消息。
另见
另见 2010, 2014, and 2018 Perl 6 advent calendar posts on MAIN
, the post Parsing command line arguments in Perl 6, and the section of Synopsis 6 about MAIN。
另外,perl6 也有 Getopt::Long。您的程序几乎无需修改即可在其中运行:
use Getopt::Long;
my $data = "file.dat";
my $length = 24;
my $verbose;
get-options("length=i" => $length, # numeric
"file=s" => $data, # string
"verbose" => $verbose); # flag
say $length;
say $data;
say $verbose;