問題の説明:

問題の説明:

私の場合、CMakeLists.txt全体を一度に編集する必要がありましたが、問題は一般化できると思います。問題は次のとおりです。

  1. 仕事にどのようなツールが良いですか?
  2. 希望の出力をどのように取得できますか?

[Optional:]

  1. sedで予約済みのスペースを消去または消去する方法はありますか?
  2. 予約済みスペースに行を追加または追加する方法はありますか?

target_include_directoriesへの2回の呼び出しは、同じパラメーターを持つことも、そうでない場合もあります。

問題の説明:

および範囲内で、最初にインデントtarget_include_directories()スペース4つのインデント)を含むすべての行を収集してwindows前に配置します)

$<$<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. インクルードブロック内では、「ウィンドウ」を含む行を一致させ、それを出力するのではなく配列に格納します。
    3. 埋め込みブロック内で閉じている角かっこを探し、見つかったらプラットフォームプレフィックスで保存された行を印刷します。

    末尾のセミコロンを処理するには、いくつかの追加処理が必要です。これを処理する1つの方法は、前のスペースと末尾のセミコロンなしで埋め込まれた行を保存し、状況に応じて装飾することです。

    これを達成する1つの方法は次のとおりです。

    #!/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
    

おすすめ記事