Ответ 1
Я бы решил это с помощью простого регулярного выражения:
string(REGEX MATCH "^(.*)\\.[^.]*$" dummy ${MYFILE})
set(MYFILE_WITHOUT_EXT ${CMAKE_MATCH_1})
get_filename_component можно использовать для удаления/извлечения самого длинного расширения.
EXT = Наибольшее расширение имени файла (.b.c из d/a.b.c)
NAME_WE = Имя файла без каталога или самого длинного расширения
У меня есть файл с точкой в его имени, поэтому мне нужно кратчайшее расширение:
set(MYFILE "a.b.c.d")
get_filename_component(MYFILE_WITHOUT_EXT ${MYFILE} NAME_WE)
message(STATUS "${MYFILE_WITHOUT_EXT}")
сообщает
-- a
но я хочу
-- a.b.c
Каков предпочтительный способ найти имя файла без кратчайшего расширения?
Я бы решил это с помощью простого регулярного выражения:
string(REGEX MATCH "^(.*)\\.[^.]*$" dummy ${MYFILE})
set(MYFILE_WITHOUT_EXT ${CMAKE_MATCH_1})
Я бы сделал:
string(REGEX REPLACE "\\.[^.]*$" "" MYFILE_WITHOUT_EXT ${MYFILE})
Регулярное выражение соответствует точке (\\.
, см. следующий абзац), за которой следует любое количество символов, которое не является точкой [^.]*
до конца строки ($
), а затем заменяет ее пустую строку ""
.
Точка метасимвола (обычно в регулярном выражении означает "соответствовать любому символу" ) должна быть экранирована с помощью \
, которая будет интерпретироваться как буквальная точка. Однако в строковых литералах CMake (например, строковых литералах C) \
является специальным символом, а необходимо также экранировать (см. Также здесь). Поэтому вы получаете странную последовательность \\.
.
Обратите внимание, что (почти все) метасимволы не должны быть экранированы в классе символов: поэтому мы имеем [^.]
, а не [^\\.]
.
Наконец, обратите внимание, что это выражение также безопасно, если в анализируемом файле нет точки (в этом случае выход соответствует входной строке).
Ссылка на документацию по командам строк.