использование perl @ARGV - PullRequest
       17

использование perl @ARGV

0 голосов
/ 24 февраля 2019

В приложении perl я передаю переменные с помощью @ARGV.Когда всегда было две переменные и всегда одинаковые две, проблем не возникало.Теперь все стало сложнее, поэтому мне нужно «очистить» @ARGV перед добавлением в него.Поэтому я подумал, что это будет работать:

    foreach (@ARGV)
            {
                pop @ARGV;
            }

Это не так.Когда есть четыре элемента, он удаляет только два.Есть идеи, почему это должно быть?Или любой другой способ его опустошения?

Ответы [ 3 ]

0 голосов
/ 24 февраля 2019

Вы прочитали документацию для pop()?Там написано:

Выводит и возвращает последнее значение массива, сокращая массив на один элемент.

Так что я не понимаю, почему вы думаете, что он будет пустыммассив.Perl имеет большой набор документации, но он бесполезен, если вы не читаете его: -)

Вы можете очистить массив, назначив ему пустой список, например:

@ARGV = ();

Но я должен сказать, что использование @ARGV для этого звучит как ужасная идея.@ARGV имеет определенную цель - он содержит аргументы командной строки, которые передаются вашей программе.Там действительно нет необходимости использовать его для чего-либо еще.Если вам нужен собственный массив, просто создайте новый массив.

0 голосов
/ 24 февраля 2019

Ваша ошибка: вы используете foreach (извлечение элементов списка) и модифицируете (pop) тот же массив !Процитируем perlsyn :

Если какая-либо часть LIST является массивом, foreach очень запутается, если вы добавите или удалите элементы в теле цикла, например, с помощью splice. Так что не делайте этого.

Ниже показано, что происходит в вашем коде:

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

print "ARGV BEFORE: ", scalar(@ARGV), "\n";

my $count = 0;
foreach my $loop (@ARGV) {
    ++$count;
    print "ARGV beginning loop ${count} for ${loop}: ", scalar(@ARGV), "\n";
    pop @ARGV;
    print "ARGV end loop ${count} for ${loop}: ", scalar(@ARGV), "\n";
}

print "ARGV AFTER: ", scalar(@ARGV), "\n";

exit 0;

Тестовый прогон:

$ perl dummy.pl 1 2 3 4
ARGV BEFORE: 4
ARGV beginning loop 1 for 1: 4
ARGV end loop 1 for 1: 3
ARGV beginning loop 2 for 2: 3
ARGV end loop 2 for 2: 2
ARGV AFTER: 2

Сравните это с правильным подходом, который повторно проверяет список на каждой итерации:

while (@ARGV) {
    ++$count;
    print "ARGV beginning loop ${count}: ", scalar(@ARGV), "\n";
    pop @ARGV;
    print "ARGV end loop ${count}: ", scalar(@ARGV), "\n";
}
$ perl dummy.pl 1 2 3 4
ARGV BEFORE: 4
ARGV beginning loop 1: 4
ARGV end loop 1: 3
ARGV beginning loop 2: 3
ARGV end loop 2: 2
ARGV beginning loop 3: 2
ARGV end loop 3: 1
ARGV beginning loop 4: 1
ARGV end loop 4: 0
ARGV AFTER: 0

При этом: ПОЖАЛУЙСТА сделайте себе одолжение ипродумайте свою архитектуру / дизайн SW.Неправильное использование переменных Perl с определенной семантикой для собственных целей - крайне плохая идея.

0 голосов
/ 24 февраля 2019

В приложении perl я передаю переменные с помощью @ ARGV.

Это плохой дизайн, и его следует избегать.Если вам нужно передать значения, используйте аргументы функции или хотя бы вашу собственную глобальную переменную.Не используйте (ab) специальную переменную для этого.

Теперь все стало сложнее, поэтому мне нужно "очистить" @ARGV перед добавлением в него.

Если вы хотите сделать массив пустым, присвойте ему пустой список:

@ARGV = ();
...