Saya pernah membuat ini yang bisa kita perbaiki:
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'
untuk menangani beberapa kasus sudut lainnya.
Perhatikan bahwa jika Anda menghapus komentar, Anda dapat mengubah arti kode ( 1-/* comment */-1diuraikan seperti 1 - -1sementara 1--1(yang akan Anda dapatkan jika Anda menghapus komentar) akan memberi Anda kesalahan). Lebih baik mengganti komentar dengan karakter spasi (seperti yang kita lakukan di sini) daripada sepenuhnya menghapusnya.
Contoh di atas harus berfungsi dengan baik pada kode ANSI C yang valid ini, misalnya yang mencoba memasukkan beberapa kasus sudut:
#sertakan <stdio.h>
int main ()
{
printf ("% d% s% c% c% c% c% c% s% s% s% d \ n",
1 - / * komentar * / - 1,
/ \
* komentar * /
"/ * bukan komentar * /",
/ * multiline
komentar * /
'"' / * komentar * /, '"',
'\' ',' "'/ * komentar * /,
'\
\
"', / * komentar * /
"\\
"/ * bukan komentar * /",
"?? /" / * bukan komentar * / ",
'??' '+' "'/ *" komentar "* /);
return 0;
}
Yang memberikan hasil ini:
#sertakan <stdio.h>
int main ()
{
printf ("% d% s% c% c% c% c% c% s% s% s% d \ n",
1- -1,
"/ * bukan komentar * /",
'"', '"',
'\' ',' "',
'\
\
"',
"\\
"/ * bukan komentar * /",
"?? /" / * bukan komentar * / ",
'??' '+' "');
return 0;
}
Keduanya mencetak output yang sama saat dikompilasi dan dijalankan.
Anda dapat membandingkan dengan output gcc -ansi -Euntuk melihat apa yang akan dilakukan oleh pra-prosesor. Kode itu juga merupakan kode C99 atau C11 yang valid, namun gccmenonaktifkan dukungan trigraph secara default sehingga tidak akan berfungsi gcckecuali jika Anda menentukan standar suka gcc -std=c99atau gcc -std=c11atau tambahkan -trigraphsopsi).
Ini juga berfungsi pada kode C99 / C11 (non-ANSI / C90) ini:
// komentar
/ \
/ komentar
// multiline \
komentar
"// bukan komentar"
(bandingkan dengan gcc -E/ gcc -std=c99 -E/ gcc -std=c11 -E)
ANSI C tidak mendukung // formkomentar. //tidak berlaku di ANSI C sehingga tidak akan muncul di sana. Satu kasus yang dibuat-buat di mana //mungkin benar-benar muncul di ANSI C (seperti yang disebutkan di sana , dan Anda mungkin menemukan sisa diskusi yang menarik) adalah ketika operator pengikat sedang digunakan.
Ini adalah kode C ANSI yang valid:
#define s(x) #x
s(//not a comment)
Dan pada saat diskusi tahun 2004, gcc -ansi -Ememang memperluas ke "//not a comment". Namun hari ini, gcc-5.4mengembalikan kesalahan pada itu, jadi saya ragu kita akan menemukan banyak kode C menggunakan konstruksi semacam ini.
sedSetara GNU dapat berupa:
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"
Jika GNU Anda sedterlalu tua untuk didukung -Eatau -z, Anda dapat mengganti baris pertama dengan:
sed -r ":1;\$!{N;b1}