Что делает «while test $# -gt 0»?

Что делает «while test $# -gt 0»?

Я пытаюсь создать функцию и, как мне кажется, нашел хороший рабочий пример, но я не понимаю всей ее логики.

А конкретно, по строке «while» может ли кто-нибудь объяснить, что такое test и что он делает? Что такое $# (разве # не является символом комментария?) и откуда берется параметр -gt 0? Не удалось найти его на странице руководства while.

Вот пример:

function my_function()
{
while test $# -gt 0
do
    $
echo "$1"
    shift
done
}

Спасибо.

решение1

Хотя #сам по себе он определенно является комментарием, $#он содержит количество параметров, переданных вашей функции.

testэто программа, которая позволяет вам выполнять различные тесты, например, если одно число больше другого числа (если ваш оператор — -gt; есть много других операторов, см. man test). Она вернет успех, если тест успешен (в данном случае, если the number of parametersIS больше 0).

команда shiftотбрасывает первый параметр. Он также уменьшает$#

Код в целом можно рассматривать как: сделать что-то с параметром (в данном случае, отобразить его на экране), затем отбросить его; повторять до тех пор, пока не останется ни одного параметра.

Если вы хотите увидеть все оставшиеся параметры, полезные для отладки, проверьте содержимое$@

решение2

$#==> параметры скрипта переданы

test==> команда оценки состояния

-gt==> представляетбольше чем

test a -gt b==> true, если a больше b, false в противном случае

Собираем все вместе:

while test $# -gt 0==> хотя передано больше параметров (причина, по которой это меняется, — сдвиг)

Сложность заключается shiftв теле цикла while.

$1==> всегда представляет первый параметр

Чтобы сделать это более конкретным, предположим, что вы передаете параметры a, bи c.

$1==> представляет a, поскольку это ваш первый параметр

вызвав now shift, aисчезает, а ваш список параметров now bи cпоэтому если вы вызываете $1now, то это bтак как this теперь первый параметр в списке. Вызов shiftеще раз ваш список параметров now просто c, поэтому $1now c. Вызов shiftеще раз оставляет список параметров пустым, поэтому условие while не будет выполнено (так как список параметров больше не больше 0, так как теперь его размер равен нулю), что приведет к завершению цикла while.

Каковы преимущества использования shiftи ссылки на текущий параметр как $1?

Это дает вам гибкость, чтобы не знать заранее в вашем скрипте, сколько параметров передается в скрипте, и независимо от этого перебирать их один за другим, ссылаясь в цикле while на текущий параметр всегда as, $1поскольку это означает начало списка параметров. При shiftиспользовании ing в конечном итоге список параметров будет пустым, поэтому важно иметь условие while для проверки, больше ли он нуля, чтобы завершить и не зацикливаться бесконечно.

решение3

Запустите скрипт ниже, чтобы понять, что означают переменные. Сохраните скрипт как somescript.shи вызовите его с некоторыми входными параметрами.

#!/bin/bash
echo "I display the total parameters passed to this script from commandline"
echo $#
echo "I display all the parameter values"
echo "Input: $@"
echo "I display the first parameter value"
echo "$1"

shift 
echo "After shift: $@"

решение4

Если вы простите мне некоторую повторность ответов, я думаю, вы найдете это полезным.

_fn() { set -- "$@" $(cat)
    while ${1+:} false ; do 
        echo "$1" && [ "$1" = "arg2" ] && echo "$1"
        $YOUR_CHK
        shift
    done
}

echo "arg2" | _fn "arg1"

ВЫХОД

arg1
arg2
arg2

Это обрабатывает как аргументы командной строки, так и stdin. Он запускает цикл только whileдля их проверки, пока у вас все еще есть хотя бы один аргумент, сохраненный в массиве параметров. Он отбрасывает каждый аргумент, который он проверяет, поэтому часть $YOUR_CHKдолжна сохранять информацию, которую вы считаете ценной тем или иным образом.

_fnбудет вести себя так же, если его содержимое будет телом скрипта или будет представлено в виде функции оболочки.

_fnобрабатывает stdin- в данном случае "arg2" echoредактируется |pipe- в первой строке, связывая setсвой позиционный параметр shell $@массив со всем, что передается в командной строке - или "$@"- И все catвыводится через $(comand substitution).

while _fn's $1Первый параметр — ${set+}мы заменяем встроенный в оболочку :trueдля удовлетворения whileусловия цикла. Как только $1не задано, эта замена не происходит, условие оценивается как falseи whileцикл прерывается.

Для каждой итерации цикла whilees _fn() echoего $1первый параметр &&в случае успеха ( echoравняетсявсегдауспешно) [ tests ]чтобы увидеть, $1равно ли строке "arg2" &&, если [ test ]успешно _fn() echoes $1снова.

$YOUR_CHKявляется нулевой операцией — это неустановленная переменная, которая не возвращает никакого значения до того, как оболочка выполнит какой-либо код.

Для каждой итерации цикла whileмы shiftудаляем $1первый параметр. Так что на итерации 1 "$@"это выглядит так:

arg1 arg2

Но после shiftпервого раза это выглядит так:

arg2

И после shiftпоследнего раза это выглядит так:

Итак, это возвращает нас к тому, ${1+:} falseчто $1теперь не установлено, оболочка не будет заменять :true, а вместо этого будет только falseоцениваться, что прерывает whileцикл и завершает_fn().

Связанный контент