g_speran has asked for the wisdom of the Perl Monks concerning the following question:

Hello Perl Monks,
	I'm sure one you see what I am doing you may be like "What in the BLEEP, are or doing or thinking".
	Well, this is why I am reaching out to the Monks, as i believe there has to be a better way to do this.
	
	I am trying to locate all the element in the @ARGV that were passed via command line and ONLY delete some of them.
	in the example, I want to delete --config and --enter
	
	Now this is only a snippet of the code
	
	The results I get are now expected, but there has to be a much simpler way
> splice_tst.pl --debug --config --enter --config --config --enter +--help
use strict; Splice_Array("--config"); Splice_Array("--enter"); sub Splice_Array { print "Before Array Splicing: \n"; print "\t" . join(',', @ARGV), "\n"; my $value=shift; print "Splicing Value: $value\n"; my @matches = grep { $ARGV[$_] eq $value} 0..$#ARGV; # Just to Cou +nt the number of times the variable was identified print "$value is located at index(s): " . join(',', @matches), "\n +"; for my $match (@matches) { # just used for a Max loop count my @index = grep { $ARGV[$_] eq $value} 0..$#ARGV; print "Index:$index[0]\n"; splice @ARGV, $index[0] ,1; } print "After Array Splicing: \n"; print "\t" . join(',', @ARGV), "\n\n\n"; }
Output: C:\Temp>splice_tst.pl --debug --config --enter --config --config --ent +er --help Before Array Splicing: --debug,--config,--enter,--config,--config,--enter,--help Splicing Value: --config --config is located at index(s): 1,3,4 Index:1 Index:2 Index:2 After Array Splicing: --debug,--enter,--enter,--help Before Array Splicing: --debug,--enter,--enter,--help Splicing Value: --enter --enter is located at index(s): 1,2 Index:1 Index:1 After Array Splicing: --debug,--help C:\Temp>

Replies are listed 'Best First'.
Re: Locate emement in array and delete
by NERDVANA (Priest) on Aug 25, 2023 at 19:51 UTC

    Well, first off, I would direct you to Getopt::Long which has just about every common option you could want for command line argument parsing. In particular, check out the option pass_through:

    pass_through (default: disabled)

    With "pass_through" anything that is unknown, ambiguous or supplied with an invalid option will not be flagged as an error. Instead the unknown option(s) will be passed to the catchall "<>" if present, otherwise through to @ARGV. This makes it possible to write wrapper scripts that process only part of the user supplied command line arguments, and pass the remaining options to some other program.

    If "require_order" is enabled, options processing will terminate at the first unrecognized option, or non-option, whichever comes first and all remaining arguments are passed to @ARGV instead of the catchall "<>" if present. However, if "permute" is enabled instead, results can become confusing.

    Note that the options terminator (default "--"), if present, will also be passed through in @ARGV.

    If that can't solve the problem, my default fall-back approach would be to just write a plain old C-style loop:

    for (my $i= 0; $i < @ARGV; $i++) { if ($ARGV[$i] eq '--config') { splice(@ARGV, $i, 1); $i-- } }
    It isn't pretty or fancy, but it lets you make all the special cases you need, like consuming additional arguments, or skipping over arguments according to the particular rules of the commandline syntax for that program. A more elegant bit of code (if your needs are really simple) is to iterate backwards:
    for (reverse 0..$#ARGV) { splice(@ARGV, $_, 1) if $ARGV[$_] eq '--config'; }
    but that doesn't give you much opportunity to handle special cases.
Re: Locate emement in array and delete
by choroba (Cardinal) on Aug 25, 2023 at 19:30 UTC
    Update: Reworked the answer to suggest the regex as the primary solution. The other way was unnecessarily complex.

    You can grep to filter a list.

    #!/usr/bin/perl use warnings; use strict; my @array = grep ! /^--(?:config|enter)$/, @ARGV; print "@array";

    If you're not working with strings, you need to use something more complex.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Locate emement in array and delete
by Anonymous Monk on Aug 26, 2023 at 12:44 UTC

    In the spirit of TMTOWTDI I offer:

    #!/usr/bin/env perl
    
    use 5.010;
    
    use strict;
    use warnings;
    
    my %remove = map {; "--$_" => 1 } qw{ config enter };
    
    {
        local $" = ', ';
        say "Before array splicing: @ARGV";
        @ARGV = grep ! $remove{$_}, @ARGV;
        say "After array splicing: @ARGV";
    }
    

    But honestly, for command-line processing I would go with NERDVANA's answer and use Getopt::Long.