#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>