问题陈述:

问题陈述:

就我而言,我需要立即编辑一大堆 CMakeLists.txt - 但我认为这个问题可以概括。问题是:

  1. 哪种工具更适合这项工作?
  2. 我将如何实现所需的输出?

[Optional:]

  1. 有没有办法清空/擦除 sed 中的保留空间?
  2. 有没有办法在保留空间中添加或追加行?

两个 target_include_directories 调用可能有也可能没有相同的参数。

问题陈述:

在 和的范围内target_include_directories(,首先)收集所有包含缩进的行windows(缩进 4 个空格)并将它们放在 之前)

现在,$<$<PLATFORM_ID:Windows>:在包含 的行块之前插入正确的缩进(在上面定义的范围内),并在包含 的行块之后windows追加包含缩进的一行。>windows

还要确保包含每个块的参数的最后一行没有分号,而其他所有行都有。

迄今为止所做的研究:

下面的行收集包含窗口的行并将它们放在正确的位置,但没有缩进,也没有装饰。

sed ':j;/^$/h;/target_include_directories(/,/)/{/windows/{H;d};/)/{H;x;D;G;bj}}' CMakeLists.txt

样本数据:

...
##############
# Unique Big Block
##############
if(some_condition)
    target_include_directories(foo Public
        arg0floor;
        arg1windowsred;
        arg2chairs;
        arg3bluewindows;
        arg4tables;
        ...
        argnwalls
    )
elseif(some_other_condition)
    target_include_directories(foo Public
        arg0yeast;
        arg1windowsbroken;
        arg2barley;
        arg3wavywindows;
        arg4water;
        ...
        argnsugar
    )
endif()
##############
# Other Unique Big Block
##############
...

预期输出:

...
##############
# Unique Big Block
##############
if(some_condition)
    target_include_directories(foo Public
        arg0floor;
        arg2chairs;
        arg4tables;
        ...
        argnwalls
        $<$<PLATFORM_ID:Windows>:
            arg1windowsred;
            arg3bluewindows;
            ...
            argkwindowsblack
        >
    )
elseif(some_other_condition)
    target_include_directories(foo Public
        arg0yeast;
        arg2barley;
        arg4water;
        ...
        argnsugar
        $<$<PLATFORM_ID:Windows>:
            arg1windowsbroken;
            arg3wavywindows;
            ...
            argkmilkywindows
        >
    )
endif()
##############
# Other Unique Big Block
##############
...

答案1

  1. 我同意博多、AWK 或 Perl 更适合。我在这里使用 AWK,它足以完成这项工作。

  2. 以下是涉及的步骤。 AWK 是一种基于记录的模式匹配语言;默认情况下,一条记录是一行。所以在这种情况下,我会编写一个程序

    1. 查找target_include_directories,并注意我们现在位于包含块中;
    2. 当在包含块中时,匹配包含“windows”的行,并将它们存储在数组中而不是输出它们;其他行按原样输出;
    3. 在包含块中时,查找右括号;找到后,输出存储的行以及平台前缀。

    处理行尾分号涉及一些额外的处理;处理这个问题的一种方法是存储不带前导空格和尾随分号的包含行,并根据上下文对它们进行修饰。

    一种实现方式如下:

    #!/usr/bin/gawk -f
    
    # Note the start of a block, clear the memorised includes,
    # print the current line and skip to the next one
    /target_include_directories/ {
        in_include_block = 1
        delete includes
        print
        next
    }
    
    # In a block, if we match "windows", memorise the value without its semi-colon
    in_include_block && /windows/ {
        includes[length(includes)] = gensub(";", "", "g", $1)
    }
    
    # In an include block, when we reach the end, output the memorised includes
    in_include_block && /)/ {
        if (length(includes) > 0) {
            printf "        $<$<PLATFORM_ID:Windows>:"
            for (i = 0; i < length(includes); i++) {
                if (i > 0) {
                    printf ";"
                }
                printf "\n            %s", includes[i]
            }
            print "\n        >"
        }
        in_include_block = 0
    }
    
    # In an include block, if we don't match, print the line
    in_include_block && !/windows/
    
    # Outside include blocks, print
    !in_include_block
    

相关内容