Что означает ${- #*i} в скрипте оболочки?


В файле /etc/profile на CentOS 6 есть цикл for:

for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        if [ "${-#*i}" != "$-" ]; then
            . "$i"
        else
            . "$i" >/dev/null 2>&1
        fi
    fi
done

Что означает ${-#*i} в приведенном выше цикле for?
Спасибо за любую помощь.

3 18

3 ответа:

$- означает флаги оболочки.

${-#*i} означает флаги оболочки минус первое совпадение *i.

Если эти два не равны, то оболочка считается интерактивной (флаг i присутствует).

Смотрите верхний ответ на что означает " ${- #*i}"!= "$- "значит? on Unix & Linux by cuonglm :

$- является ли текущая опция флагами, установленными самой оболочкой, при вызове, или с помощью команды set builtin:

$ echo $-
himBH
$ set -a
$ echo $-
ahimBH

"${-#*i}" синтаксис для удаления строки: (из POSIX документация )

${параметр#[слово]}

Удалить Наименьший Шаблон Префикса. То слово должно быть расширено, чтобы произвести шаблон. Расширение параметра должно тогда привести к параметру, с наименьшей частью префикса, соответствующей шаблону удаленный.

Если присутствует, слово не должно начинаться с без кавычек '#'.

${параметр##[слово]}

Удалить Самый Большой Шаблон Префикса. Слово должно быть расширено, чтобы произвести шаблон. Расширение параметра должно тогда привести к параметру, с наибольшая часть префикса соответствует удаленному шаблону.

Итак, ${-#*i} удалите самую короткую строку до первого символа i:

enter code here
$ echo "${-#*i}"
mBH

В вашем случае, if [ "${-#*i}" != "$-" ] проверка, является ли ваша оболочка интерактивно или нет.

Tl; dr:

Условный [ "${-#*i}" != "$-" ] вычисляется как логический true , если текущая оболочка интерактивна, в этом случае код выхода устанавливается в 0, сигнализируя true, что приводит к выполнению ветви then оператора enclosing if.

Условный и код в вопросе в целом намеренно используют только POSIX-совместимый синтаксис и команды языка оболочки чтобы быть portable (работа со всеми POSIX- совместимыми оболочками, которые могут действовать как /bin/sh).

обратите внимание, что если bash можно было бы принять за оболочку, например, то то же самое условное условие можно было бы более читабельно выразить как
[[ $- == *i* ]]


Объяснение

  • ${-#*i} является расширением параметра , которое удаляет самый короткий префикс (#), соответствующий шаблону *i из значения именованного параметра $- (именованным параметром является чаще всего называется переменной ).

  • $- является специальным параметром , который (ссылка и курсив добавлены):

    Расширяется до текущегопараметра флагов (однобуквенные имена параметров, объединенные в строку ), как указано при вызове, специальной встроенной командой set или неявно оболочкой.

  • интерактивная оболочка неявно добавляет флаг опции i к значению $-; другими словами: наличие буквы i в значении $- означает, что оболочка под рукой является интерактивной, и, наоборот, отсутствие i означает, что оболочка является неинтерактивной.

  • Таким образом, при расширении параметра ${-#*i} шаблон *i будет совпадать только внутри значения $-, если присутствует i, и, если это так, то в силу удаления того, что *i совпало, возвращает a подстрока (суффикс, в данном случае) $-.
    Другими словами: только в интерактивной оболочке ${-#*i} не равно $-, потому что в неинтерактивной оболочке - из - за отсутствия i - расширение параметра не имеет эффекта, и два операнда равны.


Что код в вопросе делает в целом:

Короче говоря: код использует скрипты оболочки, которые он находит в /etc/profile.d, чтобы инициализировать текущую оболочку; более конкретно:

  • Скрипты (файлы с именем *.sh), расположенные в каталоге /etc/profile.d, которые читаются текущим пользователем (-r), передаются в . (точка) утилиты по очереди, в алфавитном порядке. Утилита dot выполняет команды из каждого файла в текущей оболочке , как правило, для определения псевдонимов, функций и переменных окружения. Это обычно известно как sourcing a файл.

  • выходные данные , создаваемые каждым исходным скриптом, обрабатываются по-разному в зависимости от того, является ли текущая оболочка интерактивной или нет:

    • интерактивная оболочка : выходные данные передаются через (будут видны в интерактивной оболочке).

    • неинтерактивная оболочка : выход подавлен (>/dev/null 2>&1 является ли POSIX-совместимым способом заставить замолчать как stdout, так и поток stderr).