从CMake execute_进程内部运行awk

从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 " " $

我试图在CMake
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
和to
sh
,因此命令读取(缩短)
“${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()