【问题标题】:Strip filename (shortest) extension by CMake (get filename removing the last extension)通过 CMake 去除文件名(最短)扩展名(获取文件名删除最后一个扩展名)
【发布时间】:2015-05-05 09:31:29
【问题描述】:

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

查找没有最短扩展名的文件名的首选方法是什么?

【问题讨论】:

    标签: cmake


    【解决方案1】:

    我愿意:

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

    正则表达式匹配一个点(\\.,见下一段),后跟任意数量的不是点[^.]*的字符,直到字符串的末尾($),然后将其替换为一个空字符串""

    元字符点(通常在正则表达式中表示“匹配任何字符”)需要用\ 转义才能被解释为文字点。但是,在 CMake 字符串文字(如 C 字符串文字)中,\ 是一个特殊字符,need to be escaped as well(另请参阅here)。因此你得到了奇怪的序列\\.

    请注意(几乎所有)metacharacters do not need to be escaped within a Character Class:因此我们有[^.] 而不是[^\\.]

    最后,请注意,如果分析的文件名中没有点,则此表达式也是安全的(在这种情况下,输出对应于输入字符串)。

    链接到string command documentation

    【讨论】:

    • 你说得对,单线也可以。但是双反斜杠的需要与 C 字符串文字无关 - 只是反斜杠也是 CMake 的转义字符导致它的事实。
    • @Angew 你是说the answer I linked错了吗?
    • 是的;我对答案的影响发表了评论。
    • @Angew 我编辑了我的答案,我在 cmake 文档中找到了正确的参考
    • 顺便说一下,如果你只是想更改扩展(而不是完全删除它)你可以做STRING(REGEX REPLACE "[^.]*$" "newext" MYFILE_WITH_NEW_EXT ${MYFILE_WITH_OLD_EXT})(你不需要@987654337 @)。那有用吗?不特别,但我认为它很整洁。
    【解决方案2】:

    CMake 3.14 开始,可以直接使用get_filename_component 执行此操作。

    NAME_WLE:没有目录或最后一个扩展名的文件名

    set(INPUT_FILE a.b.c.d)
    get_filename_component(OUTPUT_FILE_WE ${INPUT_FILE} NAME_WE)
    get_filename_component(OUTPUT_FILE_WLE ${INPUT_FILE} NAME_WLE)
    

    OUTPUT_FILE_WE 将设置为 aOUTPUT_FILE_WLE 将设置为 a.b.c

    【讨论】:

      【解决方案3】:

      我会用一个简单的正则表达式来解决这个问题:

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

      【讨论】:

      • 我相信可以一行完成,请在下面查看我的答案。
      【解决方案4】:

      在 CMake 3.20 及更高版本中,cmake_path 命令现在提供了一个优雅的解决方案:

       cmake_path(GET <path-var> STEM [LAST_ONLY] <out-var>)
      

      其中STEM 指的是扩展名之前的文件名部分。 cmake_path 命令取代了get_filename_component 命令。

      因此,在您的示例 a.b.c.d 中,以下代码获取文件名的主干:

      cmake_path(GET MYFILE STEM MYFILE_WITHOUT_EXT)
      message(STATUS ${MYFILE_WITHOUT_EXT})
      

      产生:

      a
      

      但是这个带有LAST_ONLY 的代码抓住了词干,但只考虑最后一个扩展名作为文件扩展名:

      cmake_path(GET MYFILE STEM LAST_ONLY MYFILE_WITHOUT_EXT)
      message(STATUS ${MYFILE_WITHOUT_EXT})
      

      产生:

      a.b.c
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-29
        • 1970-01-01
        • 2012-05-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多