Raj
Raj

Reputation: 767

Deleting first multi line comments from all *c files

I have lot of c files in a directory. Each files will start with multi line comment like below and starts with include like

#include<stdio.h>. 

   // This is a c File

   // This File does sampling the frequency

   /* This uses the logic ...
   .....
   .....
   */

#include<stdio.h>

I need to remove all the comments line at the start of all the .c files if they are present. Some files will not have these comment lines. In that case, it should not do anything. This should remove only the first multi line comments. Subsequent multi line comments should be as it is.

How to do this in perl or shell?

Thanks in advance

Upvotes: 0

Views: 471

Answers (3)

Axeman
Axeman

Reputation: 29854

I had a pretty easy solution, if #include could be considered a stopper:

use strict;
use warnings;
use English qw<$RS>;
use English qw<@LAST_MATCH_START>;

*::STDIN = *DATA{IO};
my $old_rs = $RS;
local $RS = "*/";
local $_;

while ( <> ) { 
    if ( m{/[*](?:.(?!:[*]/))*\n(?sm-ix:.(?!:[*]/))*[*]/}m ) {
        substr( $_, $LAST_MATCH_START[0] ) = '';
        print;
        last;
    }
    print;
    last if m/^\s*#include\b/m;
}
$RS = $old_rs;
print while <>;

__DATA__
##include<stdio.h>. 

   // This is a c File

   // This File does sampling the frequency

   /* A mline comment not multi */

   /* This uses the logic ...
   .....
   .....
   */

#include<stdio.h>

Notice that I had to change the initial #include so that the script works. It seemed simple to me that if I wanted multi-line comments, the simplest solution was to make '*/' my record separator, instead of doing a lot of switching on the individual lines.

But the lookahead, requires buffering and made a messier solution:

use strict;
use warnings;
use English qw<$RS>;
use English qw<@LAST_MATCH_START>;

*::STDIN = *DATA{IO};
my $old_rs = $RS;
local $RS = "*/";
local $_;

my ( $rin, $rie );
my $mline = '';
my $buffer;

while ( <> ) { 
    if ( m{/[*](?:.(?!:[*]/))*\n(?sm-ix:.(?!:[*]/))*[*]/}m ) {
        my $split = $LAST_MATCH_START[0];
        print substr( $_, 0, $split );
        $mline = substr( $_, $split );
        last;
    }
    print;
}
$RS = $old_rs;
while ( <> ) { 
    $buffer .= $_;
    if ( /^\s*#include\b/ ) { 
        $mline = '';
        last;
    }
}
print $mline, $buffer;
print while <>;

__DATA__
#include<stdio.h>. 

   // This is a c File

   // This File does sampling the frequency

   /* A mutli-line comment not on multiple lines */

   /* This uses the logic ...
   .....
   .....
   */

#include<stdio.h>

Upvotes: 0

JRFerguson
JRFerguson

Reputation: 7526

#!/usr/bin/env perl
use strict;
use warnings;
my $skipping = 0;
while (<>) {
    m{^\s*//}           and next;
    m{^\s*/\*.*\*/\s*$} and next;
    if ( m{^\s*/\*} ) {
        $skipping = 1;
        next;
    }
    if ( m{^\s*\*/} ) {
        $skipping = 0;
        next;
    }
    next if $skipping;
    print;
}

...or alternatively:

#!/usr/bin/env perl
use strict;
use warnings;
while (<>) {
    next if      m{^\s*//};
    next if      m{^\s*/\*.*\*/\s*$};
    next while ( m{^\s*/\*}..m{^\s*\*/} );
    print;
}

...AND if you only want to do this for the first multi-line comment, change the match delimiters of the range from curly braces to the "?" character, to read like this:

next while ( m?^\s*/\*?..m?^\s*\*/? );

Upvotes: 0

hfs
hfs

Reputation: 2603

If you are sure that all files start with an include, you could remove all lines before the import:

perl -i -ne 'print if /^#include/..0' *.c

Upvotes: 1

Related Questions