Verifying Perl Arguments to a Subprocesses

2019-05-07 16:28发布

问题:

So I am a beginning Perl programmer. I have been using it for about a month, however only in the last week or so have I been using it for anything other than sysadmin type tasks. In doing so I ran into the following question,

Perl subprocesses are really flexible, and they don't impose many/any constraints on arguments you pass in. How is it possible to either enforce the number of arguments and/or check whether they're references, scalars etc etc?

To clarify, here's what I currently do for Perl subprocesses:

sub mySub{
    ($a, $b) = @_;
    continue and use these methods
 }

But this provides no guarantees about what $a and $b hold. Is there anyway to make sure they contain values, say a reference for $a and a scalar for $b?

Thanks in Advance.

EDIT: When I said scalar for $b I mean containing an integer, and not being a reference to some other datastructure.

回答1:

You can use the Params::Validate module, it provides wide possibilities of checking the argument list.

In your case, something like

validate_pos(@_, { type => HASHREF | ARRAYREF }, { type => SCALAR })

would do it (note that it doesn't have a single type for "ref"). It dies when the parameters don't match.



回答2:

You should be able to specify this using subroutine prototypes:

See http://perldoc.perl.org/perlsub.html#Prototypes for a full explanation.

sub taking a single scalar

sub foo($) {
    my $scalar = shift;
}

sub taking two scalars

sub bar($$) {
    my ($scalar1, $scalar2) = @_;
}

sub taking an array

sub baz (+*) {
    my $arrayref = shift;
}

sub taking a hash

sub quux (+%) {
    my $hashref = shift;
}


回答3:

To check whether $a is a ref you can use

if(ref($a)) 

To check what type of reference it is you can use

if (ref($a) eq "HASH") { #or ARRAY



回答4:

You can perform tests on the arguments to see what they contain. However, there is no point in checking whether a scalar is a scalar.

sub mySub{
    my ($a, $b) = @_;
    if (ref $a eq 'ARRAY') { ... } # check for array ref
    continue and use these methods
 }

A variable such as $b is already a scalar, and can only contain scalar values. A reference, for example, is a scalar value. So you will need to be more specific about what you want the variable to contain.

Counting the arguments is as simple as counting any array:

sub foo {
    my $n_args = @_;  # array is scalar context returns its size
    if (@_ < 4) {     # same thing
    ...
}

In order to validate for example an alphanumeric string, you can do

if ($arg =~ /^[\w\s]+$/) {  # contains only whitespace and alphanumerics