Как проверить, равна ли переменная одному из двух значений, используя функции 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
?
Ответы
Ответ 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...) вместо обратных ссылок для лучшей обработки строк новой строки.