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

18

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

    
задан Ren 06.02.2017 в 00:28
источник
  • Когда я прочитал название, я думал, что вы подвергли цензуре плохое слово $ {- # * i} ng ... –  Marco13 06.02.2017 в 23:50

3 ответа

12

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

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

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

    
ответ дан Andrey 06.02.2017 в 00:51
10

Смотрите главный ответ на Что делает "$ {- # * i}"!="$ -" означает? на Unix & amp; Linux cuonglm :

  

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

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

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

     
    

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

         

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

         

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

         

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

         

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

  
     

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

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

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

    
ответ дан Ren 06.02.2017 в 01:32
  • Я отредактировал ваш ответ для правильной цитаты и атрибута оригинального автора. Взгляните на ссылку в справочном центре; рекомендация заключается в том, чтобы «указывать только соответствующую часть», а не полный ответ. –  Benjamin W. 06.02.2017 в 02:16
7

TL; др:

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

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

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

Объяснение

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

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

      

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

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

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

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

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

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

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

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

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

ответ дан mklement0 06.02.2017 в 04:06