我确实尝试过sed
and awk
,但它不起作用,因为涉及的字符/
已经在命令中作为分隔符。
请让我知道如何实现这一目标。
下面是一个示例。我们要删除注释部分,即/*.....*/
/*This is to print the output
data*/
proc print data=sashelp.cars;
run;
/*Creating dataset*/
data abc;
set xyz;
run;
答案1
我想我找到了一个简单的解决方案!
cpp -P yourcommentedfile.txt
一些更新:
来自用户的引用伊尔卡丘(原文来自网友评论):
我玩了一下 gcc 的选项:-f预处理将禁用大多数指令和宏扩展(显然#define 和#undef 除外)。添加-dD也会留下定义;和标准=c89可用于忽略新样式 // 注释。即使有它们,cpp 也会用空格替换注释(而不是删除它们),并折叠空格和空行。
但我认为对于大多数情况来说这仍然是合理且简单的解决方案,如果你禁用宏扩展和其他东西,我认为你会得到很好的结果...... - 是的,你可以将其与 shell 脚本结合起来以获得更好的结果... 以及更多...
答案2
我曾经想出这我们可以将其细化为:
perl -0777 -pe '
s{
# /* ... */ C comments
/ (?<lc> # line continuation
(?<bs> # backslash in its regular or trigraph form
\\ | \?\?/
)
(?: \n | \r\n?) # handling LF, CR and CRLF line delimiters
)* \* .*? \* (?&lc)* /
| / (?&lc)* / (?:(?&lc) | [^\r\n])* # // C++/C99 comments
| (?<code> # tokenising anything else
"(?:(?&bs)(?&lc)*.|.)*?" # "strings" literals
| '\''(?&lc)*(?:(?&bs)(?&lc)*(?:\?\?.|.))?(?:\?\?.|.)*?'\'' # (w)char literals
| \?\?'\'' # trigraph form of ^
| .[^'\''"/?]* # anything else
)
}{$+{code} eq "" ? " " : $+{code}}exsg'
处理更多的极端情况。
请注意,如果您消除注释,您可以更改代码的含义(像while1-/* comment */-1
一样解析(如果您删除注释,您将获得该代码)会给您一个错误)。最好用空格字符替换注释(就像我们在这里所做的那样),而不是完全删除它。1 - -1
1--1
上面的代码应该可以在这个有效的 ANSI C 代码上正常工作,例如尝试包含一些极端情况:
#include <stdio.h> int main() { printf("%d %s %c%c%c%c%c %s %s %d\n", 1-/* 注释 */-1, /\ * 评论 */ "/* 不是评论 */", /* 多行 评论 */ '“' /* 评论 */ , '”', '\'','“'/* 评论 */, '\ \ “', /* 评论 */ “\ " /* 不是注释 */ ", "??/" /* 不是注释 */ ", '??''+'"' /* "评论" */); 返回0; }
这给出了这个输出:
#include <stdio.h> int main() { printf("%d %s %c%c%c%c%c %s %s %d\n", 1- -1, "/* 不是评论 */", '"', '"', '\'','"', '\ \ ”', “\ " /* 不是注释 */ ", "??/" /* 不是注释 */ ", '??''+'"'); 返回0; }
两者在编译和运行时打印相同的输出。
您可以与 的输出进行比较,gcc -ansi -E
看看预处理器会对其执行什么操作。该代码也是有效的 C99 或 C11 代码,但是默认情况下禁用三字母支持,因此除非您指定标准(例如或添加选项) gcc
,否则它将无法使用。gcc
gcc -std=c99
gcc -std=c11
-trigraphs
它也适用于以下 C99/C11(非 ANSI/C90)代码:
// 评论 /\ / 评论 // 多行\ 评论 “//不是评论”
(与之比较gcc -E
/ gcc -std=c99 -E
/ gcc -std=c11 -E
)
ANSI C 不支持// form
注释。//
在 ANSI C 中无效,因此不会出现在那里。一种可能真正出现在 ANSI C 中的人为案例//
(如前所述那里,您可能会发现其余的讨论很有趣)是当字符串化运算符正在使用中。
这是有效的 ANSI C 代码:
#define s(x) #x
s(//not a comment)
并且在2004年讨论的时候,gcc -ansi -E
确实将其扩展到了"//not a comment"
。然而今天,gcc-5.4
返回一个错误,所以我怀疑我们会发现很多使用这种构造的 C 代码。
GNUsed
等效项可能类似于:
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*/([\\\\%].|[^\\\\%\n\r])*|(\"($lc|[\\\\%]$lc*[^\r\n]|[^\\\\%\"])*\"|'$lc*([\\\\%]$lc*[^\r\n])?([^\\\\%']|$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"
如果您的 GNUsed
太旧而无法支持-E
或-z
,您可以将第一行替换为:
sed -r ":1;\$!{N;b1}
答案3
和sed
:
更新
/\/\*/ {
/\*\// {
s/\/\*.*\*\///g;
b next
};
:loop;
/\*\//! {
N;
b loop
};
/\*\// {
s/\/\*.*\*\//\n/g
}
:next
}
支持所有可能的(多行注释,[或和]之后的数据,);
e1/*comment*/
-------------------
e1/*comment*/e2
-------------------
/*comment*/e2
-------------------
e1/*com
ment*/
-------------------
e1/*com
ment*/e2
-------------------
/*com
ment*/e2
-------------------
e1/*com
1
2
ment*/
-------------------
e1/*com
1
2
ment*/e2
-------------------
/*com
1
2
ment*/e2
-------------------
跑步:
$ sed -f command.sed FILENAME
e1
-------------------
e1e2
-------------------
e2
-------------------
e1
-------------------
e1
e2
-------------------
e2
-------------------
e1
-------------------
e1
e2
-------------------
e2
-------------------
答案4
使用 SED 命令而不使用脚本的解决方案
给你:
sed 's/\*\//\n&/g' test | sed '/\/\*/,/\*\//d'
注意这在 OS X 上不起作用,除非您安装了gnu-sed
.但它可以在 Linux 发行版上运行。