Разбить имя файла (кратчайшее) с помощью CMake (получить имя файла, удалив последнее расширение)

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

Каков предпочтительный способ найти имя файла без кратчайшего расширения?

Ответ 1

Я бы решил это с помощью простого регулярного выражения:

string(REGEX MATCH "^(.*)\\.[^.]*$" dummy ${MYFILE})
set(MYFILE_WITHOUT_EXT ${CMAKE_MATCH_1})

Ответ 2

Я бы сделал:

string(REGEX REPLACE "\\.[^.]*$" "" MYFILE_WITHOUT_EXT ${MYFILE})

Регулярное выражение соответствует точке (\\., см. следующий абзац), за которой следует любое количество символов, которое не является точкой [^.]* до конца строки ($), а затем заменяет ее пустую строку "".

Точка метасимвола (обычно в регулярном выражении означает "соответствовать любому символу" ) должна быть экранирована с помощью \, которая будет интерпретироваться как буквальная точка. Однако в строковых литералах CMake (например, строковых литералах C) \ является специальным символом, а необходимо также экранировать (см. Также здесь). Поэтому вы получаете странную последовательность \\..

Обратите внимание, что (почти все) метасимволы не должны быть экранированы в классе символов: поэтому мы имеем [^.], а не [^\\.].

Наконец, обратите внимание, что это выражение также безопасно, если в анализируемом файле нет точки (в этом случае выход соответствует входной строке).

Ссылка на документацию по командам строк.