Удаление первых многострочных комментариев из всех файлов * c

#perl #shell

#perl #оболочка

Вопрос:

У меня много файлов c в каталоге. Каждый файл будет начинаться с многострочного комментария, подобного приведенному ниже, и будет начинаться с включения подобного

 #include<stdio.h>. 

   // This is a c File

   // This File does sampling the frequency

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

#include<stdio.h>
  

Мне нужно удалить все строки комментариев в начале всех файлов .c, если они присутствуют. В некоторых файлах не будет этих строк комментариев. В этом случае он ничего не должен делать. Это должно удалить только первые многострочные комментарии. Последующие многострочные комментарии должны быть такими, какие они есть.

Как это сделать в perl или shell?

Заранее спасибо

Комментарии:

1. Строка заголовка не соответствует содержанию вопроса?

2. Важная недостающая информация: Этого первого #include не было в вашем оригинале, я полагаю, это ошибка редактора? Какое правило применяется для «первого комментария»? Комментарии перед любыми #include утверждениями?

3. Как бы вы определили случай «Его там нет»? Кажется, что вам всегда приходилось заглядывать вперед, чтобы увидеть, был ли #include , чтобы узнать, хотите ли вы удалить многострочный комментарий. И кто когда-либо думал о том, чтобы поместить includes ПЕРЕД документацией.

4. Удаление кучи уведомлений об авторских правах?

Ответ №1:

Если вы уверены, что все файлы начинаются с include, вы могли бы удалить все строки перед импортом:

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

Комментарии:

1. Я хочу сделать это в цикле в сценарии оболочки

2. -n параметр командной строки является циклом. Он использует неявный while (<>) цикл вокруг скрипта.

3. Вам не нужен цикл. *.c указывает все файлы c, а с параметром -n perl считывает весь файл с неявным циклом while

4. @Aki Вы забыли упомянуть, что -n опция использует неявный цикл while.

5. я упоминал об этом, может быть, неправильная пунктуация 🙂

Ответ №2:

 #!/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;
}
  

…или в качестве альтернативы:

 #!/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;
}
  

… И если вы хотите сделать это только для первого многострочного комментария, измените разделители диапазона соответствия с фигурных скобок на символ «?», чтобы читать следующим образом:

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

Комментарии:

1. Я хочу сделать это только для первого многострочного комментария. Последующие несколько команд должны быть представлены как есть

2. На всякий случай создайте новые файлы в другом каталоге.

Ответ №3:

У меня было довольно простое решение, если #include его можно было считать ограничителем:

 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*#includeb/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>
  

Обратите внимание, что мне пришлось изменить начальные #include , чтобы скрипт работал. Мне показалось простым, что если я хочу многострочные комментарии, то самым простым решением было сделать '*/' мой разделитель записей вместо того, чтобы делать много переключений по отдельным строкам.

Но предварительный просмотр требует буферизации и создал более запутанное решение:

 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*#includeb/ ) { 
        $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>