/ / Jak mogę zignorować komentarze C podczas przetwarzania pliku źródłowego C za pomocą Perla? - perl

Jak mogę zignorować komentarze C podczas przetwarzania pliku źródłowego C za pomocą Perla? - perl

Używam kodu, który czyta pliki, wykonuje parsowanie, ale muszę zignorować wszystkie komentarze. Istnieją dobre wyjaśnienia, jak go prowadzić, jak odpowiedź na Jak mogę usunąć wielowierszowe komentarze C z pliku za pomocą Perla?

$/ = undef;
$_ = <>;
s#/*[^*]**+([^/*][^*]**+)*/|("(\.|[^"\])*"|"(\.|[^"\])*"|.[^/""\]*)#defined $2 ? $2 : ""#gse;
print;

Moim pierwszym problemem jest to, że po uruchomieniu tej linii $/ = undef; mój kod nie działa poprawnie. Właściwie to nie wiem, co to robi, ale jeśli mógłbym to odwrócić po zignorowaniu wszystkich komentarzy, byłoby to pomocne.

Ogólnie, jaki jest użyteczny sposób ignorowania wszystkich komentarzy bez zmiany pozostałej części kodu?

Odpowiedzi:

1 dla odpowiedzi № 1

Chcesz to zrobić $/ lokalny, jak w

$_ = do { local $/; <> };

lub

{
local $/;
$_ = <>;
#...
}

Alternatywnie możesz użyć Plik :: Slurp


2 dla odpowiedzi nr 2

awk

$ cat file.c
one
two
three // comment at the back
// comment in front
four /* another comment */
/* comment spanning
multiple
lines
*/  five
six
seven

$ awk -vRS="*/" "{ gsub(//*.*/,"");gsub("//.*","")}1" file.c
one
two
three


five
six
seven

polecenie awk ustawia separator rekordów RS do */, który jest końcowym znacznikiem komentarza w stylu multilinii. więc iteruje rekordy, sprawdzając /*, tag otwierający, a następnie otrzymaj wszystko, co jest przed /*. ta koncepcja jest prosta i nie trzeba do tego tworzyć skomplikowanego wyrażenia regularnego. Podobnie, jeśli miałbyś to zrobić w Pythonie

>>> data=open("file").read()
>>> for item in data.split("*/"):
...     if "//" in item: item=item.split("//")[0]
...     if "/*" in item: item=item.split("/*")[0]
...     print item
...
one
two
three


five
six
seven

1 dla odpowiedzi nr 3

Jeśli usuwasz „zagnieżdżone” komentarze, tj .:

/* This is a comment
/* that has been re-commented */ possibly /* due to */
various modifications */

regexp może nie być najlepszym rozwiązaniem. Zwłaszcza jeśli obejmuje to wiele linii, jak w powyższym przykładzie.

Ostatnim razem musiałem zrobić coś takiego, czytałemlinie pojedynczo, zliczając ile poziomów „/ *” (lub jakikolwiek separator był dla danego języka) i nie drukując niczego, chyba że liczba wynosiła 0.

Oto przykład - przepraszam z góry, ponieważ jest to bardzo zły Perl, ale to powinno dać ci pomysł, przynajmniej:

use strict;

my $infile = $ARGV[0]; # File name

# Slurp up input file in an array
open (FH, "< $infile")  or die "Opening: $infile";
my @INPUT_ARRAY = <FH>;
my @ARRAY;
my ($i,$j);
my $line;


# Removes all kind of comments (single-line, multi-line, nested).
# Further parsing will be carried on the stripped lines (in @ARRAY) but
# the error messaging routine will reference the original @INPUT_ARRAY
# so line fragments may contain comments.
my $commentLevel = 0;

for ($i=0; $i < @INPUT_ARRAY; $i++)
{
my @explodedLine = split(//,$INPUT_ARRAY[$i]);
my $resultLine ="";

for ($j=0; $j < @explodedLine; $j++)
{
if ($commentLevel > 0)
{
$resultLine .= " ";
}
if ($explodedLine[$j] eq "/" && $explodedLine[($j+1)] eq "*")
{
$commentLevel++;
next;
}
if ($explodedLine[$j] eq "*" && $explodedLine[($j+1)] eq "/")
{
$commentLevel--;
$j++;
next;
}
if (($commentLevel == 0) || ($explodedLine[$j] eq "n"))
{
$resultLine .= $explodedLine[$j];
}
}

$ARRAY[$i]=join(" ",$resultLine);
}


close(FH)   or die "Closing: $!";