admin管理员组文章数量:1355112
I have a file that is full of lines like:
snprintf(log_buffer,...
...
...
...
);
If I use sed, I can find these lines with "snprint.*log_buffer"
.
My issue is, I would like to add a line after the ;
of the statement:
send_to_logger_process(log_buffer);
However I cannot blindly add a line to the line after the match string, as the snprintf line can be multiple lines.
Any idea of how to make this work for sed or awk, or some other command line tool so I can do it to all the files in a directory? You can assume that there are no semicolons (;
) within the body of the snprintf
: the only ;
is at the end of the statement.
edit 01: the solution:
sed '/snprint.*log_buffer/,/;/ s/;/;\nsend_to_logger_process(log_buffer);/'
has some false positives:
static struct option long_options[] =
{
/* These options set a flag. */
{"verbose", no_argument, &verbose_flag, 1},
{"brief", no_argument, &verbose_flag, 0},
/* These options dont set a flag.
We distinguish them by their indices. */
{"chipaddr_led", required_argument, 0, 'c'},
{"togglepaddr", required_argument, 0, 't'},
{"regaddr", required_argument, 0, 'r'},
{"value", required_argument, 0, 'v'},
{"i2cport", required_argument, 0, 'i'},
{"led", required_argument, 0, 'l'},
{"mstime", required_argument, 0, 'm'},
{"dutycyle", required_argument, 0, 'd'},
{"status", required_argument, 0, 's'},
{0, 0, 0, 0}
};
send_to_logger_process(log_buffer);
I have a file that is full of lines like:
snprintf(log_buffer,...
...
...
...
);
If I use sed, I can find these lines with "snprint.*log_buffer"
.
My issue is, I would like to add a line after the ;
of the statement:
send_to_logger_process(log_buffer);
However I cannot blindly add a line to the line after the match string, as the snprintf line can be multiple lines.
Any idea of how to make this work for sed or awk, or some other command line tool so I can do it to all the files in a directory? You can assume that there are no semicolons (;
) within the body of the snprintf
: the only ;
is at the end of the statement.
edit 01: the solution:
sed '/snprint.*log_buffer/,/;/ s/;/;\nsend_to_logger_process(log_buffer);/'
has some false positives:
static struct option long_options[] =
{
/* These options set a flag. */
{"verbose", no_argument, &verbose_flag, 1},
{"brief", no_argument, &verbose_flag, 0},
/* These options dont set a flag.
We distinguish them by their indices. */
{"chipaddr_led", required_argument, 0, 'c'},
{"togglepaddr", required_argument, 0, 't'},
{"regaddr", required_argument, 0, 'r'},
{"value", required_argument, 0, 'v'},
{"i2cport", required_argument, 0, 'i'},
{"led", required_argument, 0, 'l'},
{"mstime", required_argument, 0, 'm'},
{"dutycyle", required_argument, 0, 'd'},
{"status", required_argument, 0, 's'},
{0, 0, 0, 0}
};
send_to_logger_process(log_buffer);
Share
Improve this question
edited Mar 31 at 18:26
Jonathan Leslie
asked Mar 31 at 16:11
Jonathan LeslieJonathan Leslie
356 bronze badges
5 Answers
Reset to default 2Perhaps:
awk '
/snprintf\(log_buffer/ { m=1 }
m && sub(/\);/, "&\nsend_to_logger_process(log_buffer);\n") { m=0 }
1;
' file
Or:
awk '
/snprintf\(log_buffer/, sub(/\);/, "&\nsend_to_logger_process(log_buffer);\n") {}
1;
' file
Assumes there are not two snprintf
on the same line.
A Perl approach that does handle multiple occurences on a single line:
perl -gpe 's/snprintf\(log_buffer[^;]+;/$&\nsend_to_logger_process(log_buffer);\n/g' file
A similar approach can be used with GNU sed with -z
option as long as file is not too large.
You can use an address range to only apply the substitution to the snprintf "block", and use the ;
as the place where the new line should go, as it can't occur anywhere else.
sed '/snprint.*log_buffer/,/;/ s/;/;\nsend_to_logger_process(log_buffer);/'
You can exclude single-line snprintf commands by specifying you're only interested in lines not containing a semicolon:
sed '/snprint.*log_buffer[^;]*$/,/;/ s/;/;\nsend_to_logger_process(log_buffer);/'
# ~~~~~~
Using any awk:
$ awk '
{ print }
/snprint.*log_buffer/ { f=1 }
f && /;/ { print "send_to_logger_process(log_buffer);"; f=0 }
' file
snprintf(log_buffer,...
...
...
...
);
send_to_logger_process(log_buffer);
This might work for you (GNU sed):
sed '/snprintf.*log_buffer/!b;/;/bb;:a;n;/;/!ba;:b;a add a line' file
If a line does not contains snprintf.*log
dismiss it.
Otherwise if that same line contains a ;
then add a line of your choice.
Otherwise, keep reading until a line containing ;
and then add a line of your choice.
It’s quite easy with Raku/Sparrow, using range construction:
# find all blocks delimited by start / stop
# expressions
between: { "sptintf(log_buffer" } { ";" }
:any:
end:
code: <<RAKU
!raku
# update all matched blocks
for streams().values -> $block {
# line number of the bottom
# of a block
my $line-num = $block<>.tail()<index>;
# update file in place appending required
# chunk
replace(
"/path/to/file.txt",
$line-num,
$block<>.tail()<data> ~
"send_to_logger_process(log_buffer);"
);
}
RAKU
本文标签:
版权声明:本文标题:awk - Adding an additional line of code to a file after the logical end of a statement with a match string - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1743935690a2564639.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论