ฉันเคยคิดเกี่ยวกับสิ่งนี้ซึ่งเราสามารถปรับแต่งให้:
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'
เพื่อจัดการกรณีมุมเพิ่มเติมอีกไม่กี่
โปรดทราบว่าหากคุณลบความคิดเห็นคุณสามารถเปลี่ยนความหมายของรหัส ( 1-/* comment */-1
ถูกแยกวิเคราะห์1 - -1
ในขณะที่1--1
(ซึ่งคุณจะได้รับหากคุณลบความคิดเห็น) จะทำให้เกิดข้อผิดพลาด) เป็นการดีกว่าที่จะแทนที่ความคิดเห็นด้วยอักขระเว้นวรรค (ดังที่เราทำที่นี่) แทนที่จะเป็นการลบออกทั้งหมด
ข้างต้นควรทำงานอย่างถูกต้องในรหัส ANSI C ที่ถูกต้องเช่นอินสแตนซ์ที่พยายามรวมมุมเล็ก ๆ น้อย ๆ :
#include <stdio.h>
int หลัก ()
{
printf ("% d% s% c% c% c% c% c% c% s% s% d \ n",
1 - / * comment * / - 1,
/ \
* ความคิดเห็น * /
"/ * ไม่ใช่ความคิดเห็น * /"
/ * multiline
ความคิดเห็น * /
'' '/ * ความคิดเห็น * /,' "',
'\' ',' "'/ * ความคิดเห็น * /,
'\
\
"', / * ความคิดเห็น * /
"\\
"/ * ไม่ใช่ความคิดเห็น * /"
"?? /" / * ไม่ใช่ความคิดเห็น * / "
'??' '+' "'/ *" ความคิดเห็น "* /);
กลับ 0
}
ซึ่งให้ผลลัพธ์นี้:
#include <stdio.h>
int หลัก ()
{
printf ("% d% s% c% c% c% c% c% c% s% s% d \ n",
1- -1
"/ * ไม่ใช่ความคิดเห็น * /"
'' ',' "',
'\' ',' "',
'\
\
"'
"\\
"/ * ไม่ใช่ความคิดเห็น * /"
"?? /" / * ไม่ใช่ความคิดเห็น * / "
'??' '+' "');
กลับ 0
}
ทั้งการพิมพ์เอาต์พุตเดียวกันเมื่อคอมไพล์และรัน
คุณสามารถเปรียบเทียบกับผลลัพธ์ของgcc -ansi -E
เพื่อดูว่าตัวประมวลผลล่วงหน้าทำอะไรได้บ้าง รหัสนั้นยังเป็นรหัส C99 หรือ C11 ที่ถูกต้องอย่างไรก็ตามgcc
ปิดใช้งานการสนับสนุน trigraph ตามค่าเริ่มต้นดังนั้นจึงไม่สามารถใช้งานได้gcc
เว้นแต่คุณจะระบุมาตรฐานเช่นgcc -std=c99
หรือgcc -std=c11
หรือเพิ่ม-trigraphs
ตัวเลือก)
นอกจากนี้ยังทำงานกับรหัส C99 / C11 (ไม่ใช่ ANSI / C90) นี้:
// ความคิดเห็น
/ \
/ ความคิดเห็น
// multiline \
คิดเห็น
"// ไม่ใช่ความคิดเห็น"
(เปรียบเทียบกับgcc -E
/ gcc -std=c99 -E
/ gcc -std=c11 -E
)
ANSI C ไม่สนับสนุน// form
ความคิดเห็น //
ไม่ถูกต้องใน ANSI C ดังนั้นจะไม่ปรากฏที่นั่น กรณีที่วางแผนไว้อย่างหนึ่งซึ่ง//
อาจปรากฏขึ้นจริงใน ANSI C (ดังที่ระบุไว้ที่นั่นและคุณอาจพบว่าส่วนที่เหลือของการสนทนาที่น่าสนใจ) คือเมื่อตัวดำเนินการstringifyใช้งานอยู่
นี่คือรหัส ANSI C ที่ถูกต้อง:
#define s(x) #x
s(//not a comment)
และในเวลาของการอภิปรายในปี 2004 ที่ไม่แน่นอนขยายไปยังgcc -ansi -E
"//not a comment"
อย่างไรก็ตามในวันนี้gcc-5.4
ส่งคืนข้อผิดพลาดดังนั้นฉันสงสัยว่าเราจะพบรหัส C จำนวนมากโดยใช้โครงสร้างชนิดนี้
ค่าsed
เทียบเท่าของGNU อาจเป็นดังนี้:
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"
หาก GNU ของคุณsed
เก่าเกินไปที่จะสนับสนุน-E
หรือ-z
คุณสามารถแทนที่บรรทัดแรกด้วย:
sed -r ":1;\$!{N;b1}