In my case I need to edit a big bunch of CMakeLists.txt at once - but I think this problem can be generalized. The questions are:
- Which tool is better for the job?
- How would I achieve the desired output?
[Optional:]
- Is there a way to empty/erase the hold space in sed?
- Is there a way to prepend or append lines in the hold space?
Both target_include_directories calls may or may not have identical arguments.
Problem Statement:
Within the range of target_include_directories(
and the first )
collect all the lines containing windows
indent them (by 4 spaces) and put them before the )
.
Now insert $<$<PLATFORM_ID:Windows>:
with correct indentation before the block of lines containing windows
(inside the range defined above) and append one line containing an indented >
after the block of lines containing windows
.
Also make sure the last line containing arguments of each block has no semicolon and all the others do.
Research done so far:
The following line collects the lines containing windows and puts them to the right place, but without indentation and without the decoration.
sed ':j;/^$/h;/target_include_directories(/,/)/{/windows/{H;d};/)/{H;x;D;G;bj}}' CMakeLists.txt
Sample data:
...
##############
# 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
##############
...
Expected output:
...
##############
# 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
##############
...
awk
orperl
are better suited thansed
awk
then. Could you point out some names of the mechanisms inawk
I might need for this task?/target_include_directories(.*/{h;s// $<$<PLATFORM_ID:Windows>:/;x;}
. Additionally, you seldom need to loop insed
, letsed
loop for you:sed '/target_include_directories(.*/{h;s// $<$<PLATFORM_ID:Windows>:/;x;};//,/)/{/windows/{s/^/ /;H;d;};/)/{H;x;};}'
. So you were already pretty close. But this comment is just meant for improving yoursed
understanding. I'd use Python for such a task.The empty regular expression ‘//’ repeats the last regular expression match
@Philippos ... I will meditate over this one-line of beauty. I extended it to my needs a bitsed '/target_include_directories(.*/{h;s// $<$<PLATFORM_ID:Windows>:/;x;};//,/)/{/windows/{s/^/ /;H;d;};/)/{s/^\(\s*\))/\1\1>\n\1)/;H;x;};}'
. Thank you so much!