从 CMake 中的 REGEX REPLACE 中排除包含特定字符串的行
Excluding lines containing a specific string from REGEX REPLACE in CMake
这是我的第一个 post 但多年来我一直在使用 Whosebug。谢谢你每次都帮我。
我正在 CMake 中编写一个脚本,该脚本应该重写 .cfg 文件的一部分(它是来自 Ogre 3D 引擎的 resources.cfg 文件)以便:
- cmake配置运行时,绝对路径根据系统设置
- 安装时,所有文件都被复制到一个文件夹中,并设置了相对路径
我将只关注第一部分,因为它们都很相似。这是我正在处理的资源文件:
# Resources required by the sample browser and most samples.
[Essential]
Zip=stufftochange/media/packs/SdkTrays.zip
# Resource locations to be added to the default path
[General]
FileSystem=../media #local
FileSystem=stufftochange/media/materials/scripts
FileSystem=stufftochange/media/materials/textures
FileSystem=stufftochange/media/models
FileSystem=stufftochange/media/materials/programs/HLSL_Cg
FileSystem=stufftochange/media/materials/programs/GLSL
我目前的策略是,只有没有#local 标识符的行才会受到REGEX REPLACE
语句的影响。
我当前的代码是:
file(READ ${CMAKE_SOURCE_DIR}/cfg/resources.cfg RESOURCES_FILE)
string(REGEX REPLACE
"/media"
"${OGRE_HOME_BACKSLASHES}/media"
RESOURCES_FILE_MODIFIED ${RESOURCES_FILE})
file(WRITE ${CMAKE_SOURCE_DIR}/cfg/resources.cfg ${RESOURCES_FILE_MODIFIED})
这基本上取代了所有 /media
的出现。只有当 #local
不在行尾时,我才需要替换 stufftochange
(可以是字符串 media
之前的任何内容)。我尝试以多种方式修改匹配表达式,但是当我这样做时,只有第一行和最后一行被正确替换。我怀疑这与行尾有关。
这些是我试过的一些表达方式,运气不好:
([^ #]*)=[^ ]*/media([^#\n$]*)
=[^ ]*/media([^#\n$]*)
/media([^# ]*)
/media([^#\n ]*)
当然我用了\1
和\2
来保存字符串中我想保留的部分。
我在 google 和 Whosebug 上进行了一些搜索,但找不到合适的解决方案或使用 CMake 的正则表达式替换的指南(文档非常基础)。知道我的圣杯匹配表达式是什么吗?
CMake 的正则表达式语法和文档非常有限。我希望将文件的内容转换为字符串列表,每个字符串都是文件中的一行。迭代这些使正则表达式更简单:
set(SourceFile "${CMAKE_SOURCE_DIR}/cfg/resources.cfg")
file(READ ${SourceFile} Contents)
# Set the variable "Esc" to the ASCII value 27 - basically something
# which is unlikely to conflict with anything in the file contents.
string(ASCII 27 Esc)
# Turn the contents into a list of strings, each ending with an Esc.
# This allows us to preserve blank lines in the file since CMake
# automatically prunes empty list items during a foreach loop.
string(REGEX REPLACE "\n" "${Esc};" ContentsAsList "${Contents}")
unset(ModifiedContents)
foreach(Line ${ContentsAsList})
# Don't modify the line if it contains #local at the end.
if(NOT "${Line}" MATCHES "#local${Esc}$")
string(REGEX REPLACE "=.*/media" "=${OGRE_HOME_BACKSLASHES}/media" Line ${Line})
endif()
# Swap the appended Esc character back out in favour of a line feed
string(REGEX REPLACE "${Esc}" "\n" Line ${Line})
set(ModifiedContents "${ModifiedContents}${Line}")
endforeach()
file(WRITE ${SourceFile} ${ModifiedContents})
如果你不关心保留空行,你可以使用file(STRINGS ...)
读入文件,这让生活更简单一点:
set(SourceFile "${CMAKE_SOURCE_DIR}/cfg/resources.cfg")
file(STRINGS ${SourceFile} Contents)
unset(ModifiedContents)
foreach(Line ${Contents})
# Don't modify the line if it contains #local at the end.
if(NOT "${Line}" MATCHES "#local$")
string(REGEX REPLACE
"=.*/media"
"=${OGRE_HOME_BACKSLASHES}/media"
Line ${Line})
endif()
set(ModifiedContents "${ModifiedContents}${Line}\n")
endforeach()
file(WRITE ${SourceFile} ${ModifiedContents})
可能在 string
.
的文档中找到了 CMake 正则表达式语法的最佳描述
这是我的第一个 post 但多年来我一直在使用 Whosebug。谢谢你每次都帮我。
我正在 CMake 中编写一个脚本,该脚本应该重写 .cfg 文件的一部分(它是来自 Ogre 3D 引擎的 resources.cfg 文件)以便:
- cmake配置运行时,绝对路径根据系统设置
- 安装时,所有文件都被复制到一个文件夹中,并设置了相对路径
我将只关注第一部分,因为它们都很相似。这是我正在处理的资源文件:
# Resources required by the sample browser and most samples.
[Essential]
Zip=stufftochange/media/packs/SdkTrays.zip
# Resource locations to be added to the default path
[General]
FileSystem=../media #local
FileSystem=stufftochange/media/materials/scripts
FileSystem=stufftochange/media/materials/textures
FileSystem=stufftochange/media/models
FileSystem=stufftochange/media/materials/programs/HLSL_Cg
FileSystem=stufftochange/media/materials/programs/GLSL
我目前的策略是,只有没有#local 标识符的行才会受到REGEX REPLACE
语句的影响。
我当前的代码是:
file(READ ${CMAKE_SOURCE_DIR}/cfg/resources.cfg RESOURCES_FILE)
string(REGEX REPLACE
"/media"
"${OGRE_HOME_BACKSLASHES}/media"
RESOURCES_FILE_MODIFIED ${RESOURCES_FILE})
file(WRITE ${CMAKE_SOURCE_DIR}/cfg/resources.cfg ${RESOURCES_FILE_MODIFIED})
这基本上取代了所有 /media
的出现。只有当 #local
不在行尾时,我才需要替换 stufftochange
(可以是字符串 media
之前的任何内容)。我尝试以多种方式修改匹配表达式,但是当我这样做时,只有第一行和最后一行被正确替换。我怀疑这与行尾有关。
这些是我试过的一些表达方式,运气不好:
([^ #]*)=[^ ]*/media([^#\n$]*)
=[^ ]*/media([^#\n$]*)
/media([^# ]*)
/media([^#\n ]*)
当然我用了\1
和\2
来保存字符串中我想保留的部分。
我在 google 和 Whosebug 上进行了一些搜索,但找不到合适的解决方案或使用 CMake 的正则表达式替换的指南(文档非常基础)。知道我的圣杯匹配表达式是什么吗?
CMake 的正则表达式语法和文档非常有限。我希望将文件的内容转换为字符串列表,每个字符串都是文件中的一行。迭代这些使正则表达式更简单:
set(SourceFile "${CMAKE_SOURCE_DIR}/cfg/resources.cfg")
file(READ ${SourceFile} Contents)
# Set the variable "Esc" to the ASCII value 27 - basically something
# which is unlikely to conflict with anything in the file contents.
string(ASCII 27 Esc)
# Turn the contents into a list of strings, each ending with an Esc.
# This allows us to preserve blank lines in the file since CMake
# automatically prunes empty list items during a foreach loop.
string(REGEX REPLACE "\n" "${Esc};" ContentsAsList "${Contents}")
unset(ModifiedContents)
foreach(Line ${ContentsAsList})
# Don't modify the line if it contains #local at the end.
if(NOT "${Line}" MATCHES "#local${Esc}$")
string(REGEX REPLACE "=.*/media" "=${OGRE_HOME_BACKSLASHES}/media" Line ${Line})
endif()
# Swap the appended Esc character back out in favour of a line feed
string(REGEX REPLACE "${Esc}" "\n" Line ${Line})
set(ModifiedContents "${ModifiedContents}${Line}")
endforeach()
file(WRITE ${SourceFile} ${ModifiedContents})
如果你不关心保留空行,你可以使用file(STRINGS ...)
读入文件,这让生活更简单一点:
set(SourceFile "${CMAKE_SOURCE_DIR}/cfg/resources.cfg")
file(STRINGS ${SourceFile} Contents)
unset(ModifiedContents)
foreach(Line ${Contents})
# Don't modify the line if it contains #local at the end.
if(NOT "${Line}" MATCHES "#local$")
string(REGEX REPLACE
"=.*/media"
"=${OGRE_HOME_BACKSLASHES}/media"
Line ${Line})
endif()
set(ModifiedContents "${ModifiedContents}${Line}\n")
endforeach()
file(WRITE ${SourceFile} ${ModifiedContents})
可能在 string
.