Как "FOO = myprogram" в bash делает "if (getent (" FOO "))" верным true в C? - PullRequest
1 голос
/ 18 мая 2019

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

if (getenv("FOO")) do_this_if_foo();

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

FOO= mycommand myargs

Обратите внимание, что цель этого состояла в том, чтобы активировать флаг - если вы не хотите, чтобы добавленная операция, вы просто не включили бы FOO=. Тем не менее, я никогда не видел переменную окружения, установленную таким образом. Каждый пример, который я могу найти с добавленными переменными, устанавливает значение FOO=bar mycommand myargs вместо того, чтобы оставлять его пустым.

Что именно здесь происходит, что позволяет этому флагу работать без установки? И есть ли потенциальные проблемы с реализацией переменных среды, подобных этой?

Ответы [ 2 ]

4 голосов
/ 18 мая 2019

В руководстве bash говорится:

Переменной может быть назначено выражение в виде

<i>name</i>=[<i>value</i>]

Если значение не задано, переменной присваивается пустая строка.

Обратите внимание, что "null" (в смысле, например, JavaScript null) не является частью оболочки.Когда руководство по bash говорит «пустая строка», это означает пустую строку (то есть строку с нулевой длиной).

Также :

КогдаПри выполнении простой команды оболочка выполняет следующие расширения, назначения и перенаправления слева направо.

[...]

Если имя команды не найдено, назначения переменных влияют на текущую среду оболочки.В противном случае переменные добавляются в среду выполняемой команды и не влияют на текущую среду оболочки.

Таким образом, все, что делает FOO= mycommand, это устанавливает переменную среды FOO в пустую строку, покавыполнение mycommand.Это удовлетворяет if (getenv("FOO")), поскольку оно проверяет только наличие переменной, а не наличие (не пустого) значения.

Конечно, любое другое значение также будет работать: FOO=1 mycommand, FOO=asdf mycommand и т. Д.

0 голосов
/ 18 мая 2019

FOO= - это просто установка переменной на ноль (точнее, установка переменной на нулевую байтовую строку, которая, таким образом, возвращает указатель на терминатор NUL - спасибо @CharlesDuffy). Учитывая код, который вы разместили, он может быть FOO='bananas' и вызывать то же самое поведение. Хотя писать код таким способом очень странно. Распространенной причиной для установки переменной в командной строке является передача значения для этой переменной в сценарий, например, установить флаги уровня отладки или регистрации очень часто, например, (Псевдокод):

debug=1 logLevel=3 myscript

myscript() {
    if (debug == 1) {
        if (loglevel > 0) {
            printf "Entering myscript()\n" >> log
            if (logLevel > 1) {
                printf "Arguments: %s\n" "$*" >> log
            }
        }
    }
    do_stuff()
}

С тестом "переменная существует" работать немного сложнее, потому что тогда вам нужно специально сбросить переменную, чтобы очистить флаг, вместо того, чтобы просто установить FOO=1, когда вы хотите что-то сделать, иначе ваш скрипт не ' все равно, когда FOO равно нулю или 0 или не установлено, или что-то еще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...