问题
I have an input C file (myfile.c) that looks like this :
void func_foo();
void func_bar();
//supercrazytag
I want to use a shell command to insert new function prototypes, such that the output becomes:
void func_foo();
void func_bar();
void func_new();
//supercrazytag
So far I've been unsuccessful using SED or PERL. What didn't work:
sed 's|\n\n//supercrazytag|void func_new();\n\n//supercrazytag|g' < myfile.c
sed 's|(\n\n//supercrazytag)|void func_new();\1|g' < myfile.c
Using the same patterns with perl -pe "....." didn't work either.
What am I missing ? I've tried many different approaches, including this and this and that.
回答1:
For "perl -pe", your problem is that it is processing line by line, so there is no way it will find "\n\n". If you add the -0777 flag to Perl (to make it process the whole file at once) it will work:
perl -0777 -pe "s|(\n\n//supercrazytag)|\nvoid func_new();$1|g" myfile.c
I also changed the (deprecated for this usage) \1 to $1 and added an extra "\n" to beginning of the replacement for readability.
See perlrun (Command Switches) for an explanation of the odd-looking "-0777"
回答2:
This will work:
sed '/^$/N;s|\n//supercrazytag|void func_new();\n\n//supercrazytag|' myfile.c
EDIT:
Or more concisely:
sed '/^$/N;s|\(\n//supercrazytag\)|void func_new();\n\1|' myfile.c
回答3:
This is actually an adaptation of an answer I just gave here, on detecting a certain point in a file.
In pseudocode:
1. start reading and writing lines from the file
2. when we find the end of the prototype section, insert some new text
use strict;
use warnings;
my $new_prototype = 'void func_new();';
my $seen_proto;
while (<>)
{
if (/^void \w+\(\);$/ .. /^$/)
{
# in the middle of the prototype section
$seen_proto = 1;
}
else
{
# this code is run when either before or after the prototype section
# if we have seen prototypes, we're just after that section - print
# out the new prototype and then reset our flag so we don't do it twice
print "$new_prototype\n" and $seen_proto-- if $seen_proto;
}
# print out the original line
print;
}
Put this code in process.pl and run via: perl process.pl < mycode.cpp > mycode_new.cpp
回答4:
awk '/supercrazy/{$0="void func_new()\n\n"$0}1' file
来源:https://stackoverflow.com/questions/3365260/match-and-replace-multiple-newlines-with-a-sed-or-perl-one-liner