Я пытаюсь создать функцию и, как мне кажется, нашел хороший рабочий пример, но я не понимаю всей ее логики.
А конкретно, по строке «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 parameters
IS больше 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
поэтому если вы вызываете $1
now, то это b
так как this теперь первый параметр в списке. Вызов shift
еще раз ваш список параметров now просто c
, поэтому $1
now 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
цикл прерывается.
Для каждой итерации цикла while
es _fn() echo
его $1
первый параметр &&
в случае успеха ( echo
равняетсявсегдауспешно) [ tests ]
чтобы увидеть, $1
равно ли строке "arg2"
&&
, если [ test ]
успешно _fn() echo
es $1
снова.
$YOUR_CHK
является нулевой операцией — это неустановленная переменная, которая не возвращает никакого значения до того, как оболочка выполнит какой-либо код.
Для каждой итерации цикла while
мы shift
удаляем $1
первый параметр. Так что на итерации 1 "$@"
это выглядит так:
arg1 arg2
Но после shift
первого раза это выглядит так:
arg2
И после shift
последнего раза это выглядит так:
Итак, это возвращает нас к тому, ${1+:} false
что $1
теперь не установлено, оболочка не будет заменять :true
, а вместо этого будет только false
оцениваться, что прерывает while
цикл и завершает_fn().