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 */-1
wird wie analysiert , 1 - -1
wä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 -E
zu sehen, was der Vorprozessor damit machen würde. Dieser Code ist auch gültig für C99- oder C11-Code, gcc
deaktiviert jedoch standardmäßig die Trigraph-Unterstützung, sodass er nur funktioniert, gcc
wenn Sie den Standard wie gcc -std=c99
oder angeben gcc -std=c11
oder die -trigraphs
Option 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 // form
Kommentar 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 -E
es sich in der Tat erweitert "//not a comment"
. Gibt jedoch heute gcc-5.4
einen 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 sed
zu alt ist, um -E
oder zu unterstützen -z
, können Sie die erste Zeile ersetzen durch:
sed -r ":1;\$!{N;b1}