使用 SED 命令而不使用脚本的解决方案

使用 SED 命令而不使用脚本的解决方案

我确实尝试过sedand 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 - -11--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,否则它将无法使用。gccgcc -std=c99gcc -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 发行版上运行。

相关内容