У меня есть скрипт bash, который я использую с i3wm для переключения между режимами экрана (внешний экран, внутренний экран, все или зеркало). Первая часть скрипта захватывает название экранов. Если я копирую следующую часть и запускаю в терминале:

#!/bin/bash

xrandr|grep " connected primary"|IFS=" " read INTERNAL_OUTPUT con
xrandr|awk '/ connected/ && !/ primary/'|IFS=" " read EXTERNAL_OUTPUT con
echo internal monitor is $INTERNAL_OUTPUT
echo external monitor is $EXTERNAL_OUTPUT

...

Я получаю что-то вроде

$ ./script.sh
internal monitor is eDPI
external monitor is DPI-1

Но когда я запускаю реальный скрипт, переменные пусты и все, что я вижу, это

$ ./script.sh
internal monitor is 
external monitor is 

В чем разница при установке переменных внутри скрипта?

1 ответ1

2

Вы не можете устанавливать переменные в конвейере и иметь значение, доступное вне конвейера. При запуске конвейера каждая часть запускается в своей собственной подоболочке, поэтому команда read находится в своей собственной подоболочке. Подоболочка не может изменить среду родителя, поэтому переменные, которые вы там задаете, недоступны для родителя.

Чтобы обойти это, вы можете сделать так, как говорит @AFH, и изменить команду так, чтобы печаталось только то, что вы хотите, а затем присвоить это переменной в родительской оболочке.

С другой стороны, вы можете реструктурировать команды, чтобы не зацикливаться на чтении. Я бы предпочел подход AFH, но переупорядочение может выглядеть так:

IFS=" " read INTERNAL_OUTPUT con < <(xrandr|grep " connected primary")

где мы перенаправляем ввод read из подстановки процесса, которая выполняет остальную часть команды, поэтому read все еще находится в родительской оболочке.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .