a=5; true | { true && a=10; } чему будет равно a?devops-62

Давайте детально разберем эту команду и поймем, почему результат может быть неочевидным.

Пошаговый анализ

  1. Инициализация переменной:

    a=5
    
    • Создается переменная a со значением 5 в текущей shell-сессии
  2. Конвейер (pipeline):

    true | { true && a=10; }
    
    • Команда слева от | (true) передает свой вывод (которого нет) команде справа
    • Важно: в bash каждая часть конвейера выполняется в подоболочке (subshell)
  3. Групповая команда в фигурных скобках:

    { true && a=10; }
    
    • { ...; } - группа команд, выполняемая в текущем shell-контексте
    • Но из-за конвейера вся правая часть выполняется в subshell
  4. Логическое И (&&):

    true && a=10
    
    • Если первая команда успешна (true), выполняется вторая (a=10)
    • Но выполняется это в контексте subshell!

Ключевые моменты:

  1. Subshell изоляция:

    • Изменения переменных в subshell не влияют на родительский shell
    • Конвейер (|) неявно создает subshell для правой части
  2. Фигурные скобки vs подгруппа:

    • { ...; } обычно выполняется в текущем shell, но не когда часть конвейера
    • Альтернатива - ( ... ) - всегда создает subshell

Практическая проверка

Выполним команду и проверим значение:

$ a=5; true | { true && a=10; }; echo $a
5

Альтернативные варианты

Если бы мы хотели изменить a в текущем shell:

  1. Без конвейера:

    $ a=5; { true && a=10; }; echo $a
    10
    
  2. Process Substitution (bash):

    $ a=5; true | { true && a=10; } > >(cat); echo $a
    10
    
  3. Последняя команда в конвейере без subshell (zsh):

    % a=5; true | { true && a=10; }; echo $a
    10
    

Почему так происходит?

  • В bash поведение конвейера исторически сложилось таким для безопасности
  • Изменения в subshell изолированы, чтобы не ломать состояние основного shell
  • Это предотвращает случайные изменения глобального состояния

Резюмируем: в bash при выполнении a=5; true | { true && a=10; } переменная a останется равной 5, потому что присваивание a=10 выполняется в подоболочке, созданной конвейером, и не влияет на родительский shell.