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

В файле /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} в приведенном выше для цикла?
Спасибо за любую помощь.

Ответы

Ответ 1

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

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

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

Ответ 2

Посмотрите лучший ответ на Что означает "$ {- # * i}" != "$ -" означает? на Unix и Linux cuonglm:

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

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

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

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

     

Удалить малый шаблон префикса. Слово должно быть расширено для производства   шаблон. Затем расширение параметра должно приводить к параметру,   с наименьшей частью префикса, соответствующей шаблону   удален.

     

Если присутствует, слово не должно начинаться с некорректного "#".

     

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

     

Удалить самый большой шаблон префикса. Слово должно быть расширено для создания   шаблон. Затем расширение параметра должно приводить к параметру с   самая большая часть префикса, соответствующая удалению шаблона.

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

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

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

Ответ 3

TL;DR:

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

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

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


Объяснение

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

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

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

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

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


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

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

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

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

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

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