I need to write a shell script which will input a string in my .c files after a quite complicated pattern to match.
The pattern is: )\n{,
without any tabs/spaces between the \n and the {. That's to say that I want to match with a { located in the first column of my file (this in order to ONLY match with )\n{ following function declarations in C, not the ones following loops or conditions).
void some_function_declaration(char var1, char var2)
{
I have read manuals, forums and still cannot figure the right way to write the pattern to match or find the corresponding regex. The corresponding output would be:
void some_function_declaration(char var1, char var2)
{ time_exe(__func__, cl(clock()));
rest of the function...
What follows is what I've came up with so far and doesn't work.
Try 1
sed -i '' '/)$\n{/a time_exe(__func__, cl(clock()));' >> list_func2.c
Try 2
sed -i '' '/)\n{ /a time_exe(__func__, cl(clock()));' >> list_func2.c
Try 3
sed -i '' '/)/\n{/a time_exe(__func__, cl(clock()));' >> list_func2.c
I would be very glad to hear your recommandations about this matter.
You should avoid using sed which is a line-based tool and won't handle this kind of task well.
If you insist on using sed and are using GNU sed, you can however use the -z / --null-data option which will read the whole file in one pass (reading NUL-byte separated records rather than linefeed-separated records) and will enable you to use the )\n{ pattern as you would expect :
$ { echo "line1)"; echo "{line2"; } | sed -z 's/)\n{/X/g'
line1Xline2
As this requires loading the whole file in memory, expect terrible performances for huge files.
If you like unmaintainable gibberish you can solve this problem using sed's less known P, t and D commands :
sed '/)$/{N;s/)\n{/) {\n\ttime_exe(__func__, cl(clock()));/;t;P;D}'
Try it here !
This works by loading an additional line in the pattern space (N) when a line ending in ) is encountered, trying to substitute against the two-lines pattern, and printing (P) and removing (D) the first line from the pattern space if the pattern isn't matched (otherwise t branches to the next iteration), leaving the second line in the pattern space to be used as the first line of the next iteration.
Using /first line pattern/{N;s/whole pattern/replacement/} is often good enough, but it can fail as N will consume a line you won't test the first line pattern against. This is illustrated here.
I agree with @Aaron, but if you still want exactly sed, look at this:
$ cat /tmp/del.txt
void some_function_declaration(char var1, char var2)
{
...
}
void enother_function_declaration(char var1, char var2)
{
...
}
And applying sed:
$ cat /tmp/del.txt | sed ':a;N;$!ba;s/)\n{/)\{\ntime_exe(__func__, cl(clock()));/g'
void some_function_declaration(char var1, char var2){
time_exe(__func__, cl(clock()));
...
}
void enother_function_declaration(char var1, char var2){
time_exe(__func__, cl(clock()));
...
}
I think it looks like you wanted
UPD
Let me explane..
More cross-platform compatible syntax is:
sed -e ':a' -e 'N' -e'$!ba' -e 's/)\n{/)\n{ ... ;/g'
where
':a' - creates a branch label (named a) that can be returned later'N' - appends next line to current (with \n between)'$!ba' - jumps to label a if next line is the last line's/)\n{/)\n{ ... ;/g' - makes global substitution in the single line, composed of all the lines and \nsIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With