Bash пропуска итерация във for

Трябва да напиша макрос, който получава малко аргументи към него. например ./macro.sh -wrongone -f име на файл -wrongone. Трябва да хвана грешните и да ги изброя и да направя необходимата операция върху валидните. Ето моят код:

for i in "${ArrayOfParameters[@]}"
do
    tmp=$[tmp+1]
    case "${i}" in

    "-h" | "--help")
        help
        ;;

    "-f")   
        a="${ArrayOfParameters[i+1]}"
        echo $a
        i=$[i+1]            
        ;;          

    *)
        echo -e "${red}Parameter ${i} is wrong!${NC}"
        ;;
    esac

done    

Проблемът ми е, че не знам как да направя 'filename' да бъде пропуснато по подразбиране на превключвателя :(. Всеки път, когато получа грешка, че името на файла е грешен параметър. Мислех си да пропусна една итерация. Нещо подобно в C++ .

for(int i=0;i<5;i++)
if(i==3)
i=4;

Бих искал да получа нещо подобно в Bash, но нямам идея как да го направя. Опитах

for (( i=0; i<=5; i++ ))
a="${ArrayOfParameters[i]}"

но ми връщаше всички времеви числа, а не низовете. Ще съм много благодарна за полезни отговори.


person FilOle    schedule 21.03.2015    source източник


Отговори (3)


тествахте ли първия си пример? Бих се изненадал, ако това проработи... със сигурност ще трябва да използвате някои асинхронни методи, за да го накарате да работи? Освен това, въпреки заглавието им, изглежда, че потребителят иска Label със стойност на свойството Foreground, което се променя.
person BorrajaX    schedule 21.03.2015
comment
Хм, въпреки че все още не работи, както възнамерявах :/. Тогава ще използвам други решения :P. - person FilOle; 21.03.2015
comment
@user3593720, Ако редактирате въпроса си, обяснявайки защо това не работи по предназначение, може би можем да работим по него ;-) - person BorrajaX; 21.03.2015
comment
Проблемът е все същият. Да кажем, че третият ми аргумент е -f четвъртото име на файла и петият да кажем -g. Искам програмата да пропусне четвъртия аргумент, защото ако не го пропусне *) (по подразбиране) ще ми напише съобщение. Направих всичко като във вашия код, но все още *) пише, че елементът не е пропуснат ›.‹. - person FilOle; 22.03.2015
comment
@user3593720, искаш да кажеш, че все още отпечатва четвъртия аргумент (име на файл)? Тъй като опитах с ArrayOfParameters=("-hello" "-howdy" "-foo bar" "-f" "-something else" "-g" "whatever") и той пропуска елемента след -f, скачайки от -f към -g (без да показва -something else). Или искате напълно да спрете цикъла точно когато намери -f? (ще ви трябва break за това) Тестовете ми са на Ubuntu 12.04, bash 4.2.25. Може би можете да редактирате въпроса си и да добавите новия код? - person BorrajaX; 22.03.2015
comment
О, Нвм, оправих го :P Тъп съм! За и ‹= беше проблемът, просто не го забелязах по-рано, че написах такава глупост и търсих навсякъде, само не там. - person FilOle; 22.03.2015

Не е директен отговор на вашия проблем с кодирането, но мисля, че трябва да си направите услуга и да използвате getopts (вижте тук за добър урок). Обработката на параметрите обикновено е объркана и има много ъглови случаи, така че навиването на собствени не винаги е добра идея.

person tgo    schedule 21.03.2015
comment
GNU/Linux getopt(1) е много по-гъвкав от getopts. Въпреки това не се доставя с всяка система, особено не в семейството на BSD, но обикновено е достатъчно лесно да се инсталира с мениджър на пакети. - person 4ae1e1; 21.03.2015
comment
Търсите най-лесното решение. Освен това няма представа каква система ще използва потребителят, така че трябва да напишете възможно най-универсален скрипт. - person FilOle; 21.03.2015
comment
Виждам. Все пак имайте предвид, че противно на getopt, getopts е част от bash и е така от дълго време. Така че, ако можете поне да разчитате на факта, че вашият скрипт изисква bash, трябва да сте в безопасност. Ако не можете да разчитате на факта, че е bash, ще трябва да внимавате за много неща (аритметично разширение, двойни кавички в if и т.н.) - person tgo; 21.03.2015

Мисля, че най-лесното решение е да използвате флагова променлива, която сте задали на true, ако '-f' съвпада и в началото на вашия for цикъл проверете дали този флаг е зададен, задайте го на false и използвайте continue.

skipNext=false
for i in "${ArrayOfParameters[@]}"
do
    if $skipNext
    then
        skipNext=false
        continue
    fi
    tmp=$[tmp+1]
    case "${i}" in
        "-h" | "--help")
            help
            ;;
        "-f")
            skipNext=true
            a="${ArrayOfParameters[i+1]}"
            echo $a
            i=$[i+1]            
            ;;
        *)
            echo -e "${red}Parameter ${i} is wrong!${NC}"
            ;;
    esac
done  
person Siguza    schedule 21.03.2015