Подтвердить что ты не робот

Как проверить, равна ли переменная одному из двух значений, используя функции if/или/и

В make файле GNU я хотел бы установить выходную переменную в одно значение (пусть говорят "true" ), если входная переменная равна одному из двух значений и другому значению ( "false" ), когда оно не является.

Благодаря this SO answer Я узнал о функциях and и or, и вскоре после этого я нашел функцию if. Эти функции, похоже, доступны в моей версии make, поэтому я хотел бы использовать их. Я хотел бы написать что-то вроде этого:

TEST_INPUT = `hostname`
TEST_OUTPUT = $(if $(or $(eq $(TEST_INPUT),hal9000),
                        $(eq $(TEST_INPUT),pipboy)),true,false)

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

TRUE_HOSTS = hal9000 pipboy
TEST_OUTPUT = $(if $(filter $(TEST_INPUT),$(TRUE_HOSTS)),true,false)

или subst:

TEST_OUTPUT = $(if $(and $(subst hal9000,,$(TEST_INPUT)),
                         $(subst pipboy,,$(TEST_INPUT))),
                   false,true)

но для меня это не красивый или читаемый код. Есть ли решения ближе к первому примеру (тот, который использует не существующую функцию eq)? Может быть, я вообще не понимаю цели функций if, and и or?

4b9b3361

Ответ 1

Вещь, которая нечетна относительно условий GNUmake, заключается в том, что в make не существует логического типа - все это строка. Таким образом, условные все работают с пустой строкой для "false" и всей непустой строки как "истина".

Таким образом, факт, что eq отсутствует, является annoyonace, хотя и незначительным. Как правило, вы можете получить то, что хотите, от filter или findstring, а filter часто позволяет вам искать весь список строк, соответствующих вашему второму примеру.

Если вам это действительно нужно, вы можете определить свою собственную функцию eq:

eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1)))

Что вы, к сожалению, должны использовать как $(call eq,... ,... )

Ответ 2

Ответ Криса Додда хорош, но есть угловой случай, для которого он дает неверный результат. Если обе сравниваемые переменные пустые (т.е. False), то они вернут false. Улучшенная версия:

eq = $(if $(or $(1),$(2)),$(and $(findstring $(1),$(2)),\
                                $(findstring $(2),$(1))),1)

Это сначала проверяет, не является ли какой-либо из аргументов непустым, и если используется предыдущий метод для их сравнения. В противном случае он возвращает 1, чтобы указать, что значения равны, поскольку оба они пусты.

Ответ 3

В зависимости от вашего контекста рассмотрите возможность использования GMSL (GNU Make Standard Library), который представляет собой набор функций в файле make include "..., который предоставляет управление списками и строками, целочисленную арифметику, ассоциативные массивы, стеки и отладки". См. http://gmsl.sourceforge.net/

Он имеет функцию "string equal", seq, а также ряд других полезных манипуляторов:

    TEST_INPUT = $(shell hostname -s)
    TEST_OUTPUT = $(if $(or $(call seq,$(TEST_INPUT),hal9000),
                            $(call seq,$(TEST_INPUT),pipboy)),true,false)

Кроме того, используйте синтаксис $(shell...) вместо обратных ссылок для лучшей обработки строк новой строки.