从CMake execute_进程内部运行awk
我试图在CMake从CMake execute_进程内部运行awk,awk,cmake,Awk,Cmake,我试图在CMakeexecute\u进程中运行awk,但不知何故未能获得预期的结果。我想我一定是违反了一些逃跑规则,但我不确定我还需要什么才能在这里逃跑。让我以MWE的方式进行演示 考虑以下版本.h(为了简洁起见,省略了标题保护): 现在考虑下面的直截了当的 AWK < /C>命令: awk '$1 ~ /^#define/ && $2 ~ /^LIB_(MAJVER|MINVER|PATCH|BUILD)$/ { print "set(${PRJNAME}_" $2 " " $
execute\u进程中运行awk
,但不知何故未能获得预期的结果。我想我一定是违反了一些逃跑规则,但我不确定我还需要什么才能在这里逃跑。让我以MWE的方式进行演示
考虑以下版本.h
(为了简洁起见,省略了标题保护):
现在考虑下面的直截了当的<代码> AWK < /C>命令:
awk '$1 ~ /^#define/ && $2 ~ /^LIB_(MAJVER|MINVER|PATCH|BUILD)$/ { print "set(${PRJNAME}_" $2 " " $3 ")" }' version.h
输出应该是这样的(从shell执行时也是这样):
。。。这就是我打算在从版本头生成后立即包含的内容
现在考虑下面的<代码> CMAKLISTH.TXT < /代码>:
cmake_minimum_required(VERSION 3.1)
set(PRJNAME foobar)
project (${PRJNAME})
find_program(AWK awk mawk gawk)
if(AWK MATCHES ".+-NOTFOUND")
message(FATAL_ERROR "FATAL: awk (and mawk and gawk) could not be found (${AWK}).")
else()
execute_process(
COMMAND "${AWK}" '$1 ~ /^#define/ && $2 ~ /^LIB_(MAJVER|MINVER|PATCH|BUILD)$/\ { print "set(${PRJNAME}_" $2 " " $3 ")" }' "${CMAKE_SOURCE_DIR}/version.h"
RESULT_VARIABLE AWK_EXITCODE
OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/version.cmake"
)
message(STATUS "Exit code from awk: ${AWK_EXITCODE}")
include(${CMAKE_CURRENT_BINARY_DIR}/version.cmake)
endif()
execute\u进程的输出是:
awk: cmd. line:1: '$1
awk: cmd. line:1: ^ invalid char ''' in expression
。。。这表明我试图执行的是逐字传递的,而不是去掉外部引用的参数。因此,我甚至没有费心在awk
命令中转义出现的$
,我希望必须转义
现在一种方法是将其作为文件转储到shell脚本中(并在开发过程中验证它是否与我们使用的CMake版本一起工作)。另一种方法应该是使用/bin/sh-c
,但这就提出了一个问题:如何传递一个长命令字符串
然而,考虑到应该有一种方法来实现我想要的东西,这看起来既麻烦又多余
注意:我正在Linux上使用CMake 3.12.2
我应该补充一点,我试图用以下内容替换命令
字符串,以验证我的假设,即能够用/bin/sh-c
实现这一点
COMMAND /bin/sh -c [[[ "${AWK}" '$1 ~ /^#define/ && $2 ~ /^LIB_(MAJVER|MINVER|PATCH|BUILD)$/\ { print "set(${PRJNAME}_" $2 " " $3 ")" }' "${CMAKE_SOURCE_DIR}/version.h" ]]]
结果是出现以下错误:
CMake Error at CMakeLists.txt:11:
Syntax Error in cmake code at column 180
Argument not separated from preceding token by whitespace.
-- Configuring incomplete, errors occurred!
作者的评论帮助我弄清楚发生了什么(此处转载,因为实际的评论可能会消失):
与双引号(“
)不同,单引号(”
)在语法中没有特殊意义
这就是为什么它在“…”
参数中分隔单词。在double内
带引号的字符串,双引号可以用\“
转义
因此,我重写了命令
,如下所示:
cmake_minimum_required(VERSION 3.1)
set(PRJNAME foobar)
project (${PRJNAME})
find_program(AWK awk mawk gawk)
if(AWK MATCHES ".+-NOTFOUND")
message(FATAL_ERROR "FATAL: awk (and mawk and gawk) could not be found (${AWK}).")
else()
execute_process(
COMMAND /bin/sh -c "\"${AWK}\" '$1 ~ /^#define/ && $2 ~ /^LIB_(MAJVER|MINVER|PATCH|BUILD)$/\ { print \"set(\${PRJNAME}_\" $2 \" \" $3 \")\" }' \"${CMAKE_SOURCE_DIR}/version.h\""
RESULT_VARIABLE AWK_EXITCODE
OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/version.cmake"
)
message(STATUS "Exit code from awk: ${AWK_EXITCODE}")
include(${CMAKE_CURRENT_BINARY_DIR}/version.cmake)
endif()
要点是,我正在将整个awk
命令传递给/bin/sh-c
,用双引号引用,任何嵌入外部双引号中的引号都需要转义,就像$
字符一样。与双引号(“
)不同,单引号(”
)在CMake中没有特殊意义。这就是为什么它在'…'
参数中分隔单词。在双引号字符串中,可以使用\“
@Tsyvarev对双引号进行转义,这帮助我了解了如何进行转义。谢谢为了未来访问者的利益,您将回答此问题。您是否也需要在awk脚本中转义$
以停止shell使用位置参数填充$1
,而不是awk将其用于字段?idk因为我不知道什么是“Cmake execute_process”,但是你发布的代码看起来很可疑。@EdMorton这就是为什么awk
脚本用单引号括起来的原因,所以shell不会费心将它们扩展为shell变量。如果这是整个过程,那么你就不必在awk脚本中转义双引号。在命令行sh-c“echo7 | awk'{print$0}'”
上尝试,它将输出0,而sh-c“echo7 | awk'{print\$0}'
将输出7。如果它在您的“Cmake execute_process”环境中工作,那么这很好,只是想提高标志。@EdMorton您可能看到了错误的标志。。。正如Tsyvarev如此坦率地指出的那样,CMake不会以不同的方式对待单引号和双引号。因此,sh
看到的是外部双引号中的命令,第一层转义被删除。由于CMake不关心$1
和tosh
,因此命令读取(缩短)“${AWK}”'$1~。。。{…}'${CMAKE_SOURCE_DIR}/version.h“
sh
在awk
看到它之前,没有任何业务扩展$1
。基本上你掉进了我关于CGOD和报价的陷阱……我没有看到任何标志,正如我提到的,我不知道什么是“CMAK”,我只是看到了一些可疑的代码,所以我想我会让你知道它,这样你就可以考虑它是否是一个问题。听起来不太好。
CMake Error at CMakeLists.txt:11:
Syntax Error in cmake code at column 180
Argument not separated from preceding token by whitespace.
-- Configuring incomplete, errors occurred!
cmake_minimum_required(VERSION 3.1)
set(PRJNAME foobar)
project (${PRJNAME})
find_program(AWK awk mawk gawk)
if(AWK MATCHES ".+-NOTFOUND")
message(FATAL_ERROR "FATAL: awk (and mawk and gawk) could not be found (${AWK}).")
else()
execute_process(
COMMAND /bin/sh -c "\"${AWK}\" '$1 ~ /^#define/ && $2 ~ /^LIB_(MAJVER|MINVER|PATCH|BUILD)$/\ { print \"set(\${PRJNAME}_\" $2 \" \" $3 \")\" }' \"${CMAKE_SOURCE_DIR}/version.h\""
RESULT_VARIABLE AWK_EXITCODE
OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/version.cmake"
)
message(STATUS "Exit code from awk: ${AWK_EXITCODE}")
include(${CMAKE_CURRENT_BINARY_DIR}/version.cmake)
endif()