Ich kam einmal mit bis diese , die wir verfeinern:
perl -0777 -pe '
BEGIN{
$bs=qr{(?:\\|\?\?/)};
$lc=qr{(?:$bs\n|$bs\r\n?)}
}
s{
/$lc*\*.*?\*$lc*/
| /$lc*/(?:$lc|[^\r\n])*
| (
"(?:$bs$lc*.|.)*?"
| '\''$lc*(?:$bs$lc*(?:\?\?.|.))?(?:\?\?.|.)*?'\''
| \?\?'\''
| .[^'\''"/?]*
)
}{$1 eq "" ? " " : "$1"}exsg'
um ein paar weitere Eckfälle zu behandeln.
Beachten Sie, dass , wenn Sie entfernen einen Kommentar, können Sie die Bedeutung des Codes ändern könnten ( 1-/* comment */-1wird wie analysiert , 1 - -1während 1--1(die Sie erhalten würden , wenn Sie den Kommentar entfernt) würden Sie einen Fehler). Es ist besser, den Kommentar durch ein Leerzeichen zu ersetzen (wie wir es hier tun), als ihn vollständig zu entfernen.
Das Obige sollte zum Beispiel mit diesem gültigen ANSI-C-Code funktionieren, der versucht, einige Eckfälle einzuschließen:
#include <stdio.h>
int main ()
{
printf ("% d% s% c% c% c% c% s% s% d \ n",
1 - / * Kommentar * / - 1,
/ \
* Kommentar */
"/ * kein Kommentar * /",
/ * mehrzeilig
Kommentar */
'"' /* Kommentar */ , '"',
'\'','"'/* Kommentar */,
'\
\
"', /* Kommentar */
"\\
"/ * kein Kommentar * /",
"?? /" / * kein Kommentar * / ",
'??' '+' "'/ *" Kommentar "* /);
return 0;
}
Was gibt diese Ausgabe:
#include <stdio.h>
int main ()
{
printf ("% d% s% c% c% c% c% s% s% d \ n",
1- -1,
"/ * kein Kommentar * /",
'"', '"',
'\' ',' "',
'\
\
"',
"\\
"/ * kein Kommentar * /",
"?? /" / * kein Kommentar * / ",
'??' '+' "');
return 0;
}
Beide drucken beim Kompilieren und Ausführen dieselbe Ausgabe.
Sie können mit der Ausgabe von vergleichen, um gcc -ansi -Ezu sehen, was der Vorprozessor damit machen würde. Dieser Code ist auch gültig für C99- oder C11-Code, gccdeaktiviert jedoch standardmäßig die Trigraph-Unterstützung, sodass er nur funktioniert, gccwenn Sie den Standard wie gcc -std=c99oder angeben gcc -std=c11oder die -trigraphsOption hinzufügen .
Es funktioniert auch mit diesem C99 / C11-Code (kein ANSI / C90-Code):
// Kommentar
/ \
/ Kommentar
// mehrzeilig \
Kommentar
"// kein Kommentar"
(vergleiche mit gcc -E/ gcc -std=c99 -E/ gcc -std=c11 -E)
ANSI C hat den // formKommentar von nicht unterstützt . //ist in ANSI C sonst nicht gültig und wird dort nicht angezeigt. Ein erfundener Fall //, in dem ANSI C möglicherweise wirklich vorkommt (wie dort angegeben , und Sie den Rest der Diskussion vielleicht interessant finden), ist, wenn der Operator stringify verwendet wird.
Dies ist ein gültiger ANSI C-Code:
#define s(x) #x
s(//not a comment)
Und zum Zeitpunkt der Diskussion im Jahr 2004 hat gcc -ansi -Ees sich in der Tat erweitert "//not a comment". Gibt jedoch heute gcc-5.4einen Fehler zurück, sodass ich bezweifle, dass wir mit dieser Art von Konstrukt viel C-Code finden werden.
Das GNU- sedÄquivalent könnte etwa so lauten:
lc='([\\%]\n|[\\%]\r\n?)'
sed -zE "
s/_/_u/g;s/!/_b/g;s/</_l/g;s/>/_r/g;s/:/_c/g;s/;/_s/g;s/@/_a/g;s/%/_p/g;
s@\?\?/@%@g;s@/$lc*\*@:&@g;s@\*$lc*/@;&@g
s:/$lc*/:@&:g;s/\?\?'/!/g
s#:/$lc*\*[^;]*;\*$lc*/|@/$lc*/$lc*|(\"([\\\\%]$lc*.|[^\\\\%\"])*\"|'$lc*([\\\\%]$lc*.)?[^\\\\%']*'|[^'\"@;:]+)#<\5>#g
s/<>/ /g;s/!/??'/g;s@%@??/@g;s/[<>@:;]//g
s/_p/%/g;s/_a/@/g;s/_s/;/g;s/_c/:/g;s/_r/>/g;s/_l/</g;s/_b/!/g;s/_u/_/g"
Wenn Ihre GNU sedzu alt ist, um -Eoder zu unterstützen -z, können Sie die erste Zeile ersetzen durch:
sed -r ":1;\$!{N;b1}