从CMake中的REGEX REPLACE中排除包含特定字符串的行 [英] Excluding lines containing a specific string from REGEX REPLACE in CMake

查看:1167
本文介绍了从CMake中的REGEX REPLACE中排除包含特定字符串的行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的第一篇文章,但多年来我一直在使用StackOverflow。感谢您的每一次帮助。

This is my first post but I have been using StackOverflow for years. Thanks for helping me every time.

我正在CMake中编写一个脚本,该脚本应该重写.cfg文件的一部分(这是来自的resources.cfg文件Ogre 3D引擎),以便:

I am writing a script in CMake that is supposed to rewrite a portion of a .cfg file (it is the resources.cfg file from Ogre 3D engine) so that:


  • 使用cmake运行配置时,将根据系统设置绝对路径

  • 安装时,所有文件都复制到一个文件夹中,而是设置了相对路径

我只关注第一个部分,因为它们都相似。这是我正在处理的资源文件:

I will focus only on the first part, since they are both similar. This is the resource file I am working on:

# 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 语句的影响。
我当前的代码是:

My current strategy is that only lines without the #local identifier should be affected by the REGEX REPLACE statement. My current code is:

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 事件。仅当 stufftochange (可以是字符串 media 之前的任何内容)。 > #local 不在行末。我试图以多种方式修改匹配的表达式,但是当我这样做时,只有第一行和最后一行被正确替换。我怀疑这与行尾有关。

which basically replaces all /media occurrences. I need to replace the stufftochange (that can be ANYTHING that is before string media) only if #local is not at the end of the line. I tried to modify the matching expression in lots of ways but, when I do, only the first and last line are replaced properly. I suspect that it has to do with the line endings.

这些是我尝试过的一些表达式,没有运气:

These are some of the expressions I tried, without luck:

([^ #]*)=[^ ]*/media([^#\n$]*)
=[^ ]*/media([^#\n$]*)
/media([^# ]*)
/media([^#\n ]*)

我当然使用了 \\1 \\ \2 保存我要保留的字符串部分。

Of course I used \\1 and \\2 to save the parts of the string that I want to keep.

我在google和stackoverflow上进行了一些搜索,但是无法找到使用CMake的regex替换的正确解决方案或指南(文档非常基础)。知道我的圣杯匹配表达式是什么吗?

I did a few searches on google and stackoverflow but couldn't find a proper solution or guide for using CMake's regex replace (and documentation is very basic). Any idea what my holy grail match expression would be?

推荐答案

CMake的正则表达式语法和文档非常有限。我希望将文件的内容转换为字符串列表,每个字符串都是文件中的一行。迭代这些使正则表达式简单得多:

CMake's regex syntax and documentation are pretty limited. I'd favour turning the file's contents into a list of strings, each string being a line in the file. Iterating these makes the regex much simpler:

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 ... )来读取文件,这使工作变得更简单:

If you don't care about preserving blank lines, you can use file(STRINGS ...) to read in the file, which makes life a bit simpler:

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})

可能是CMake regex语法的最佳描述在 string

Probably the best description of CMake's regex syntax is found in the docs for string.

这篇关于从CMake中的REGEX REPLACE中排除包含特定字符串的行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆