如何删除落在 /* .... */ 下的所有字符,包括 /* & */?

Sha*_*lam 13 text-processing

我确实尝试过sedand awk,但它不起作用,因为字符所涉及的字符/已经在命令中作为分隔符存在。

请让我知道我怎样才能做到这一点。

下面是一个示例示例。我们要删除评论部分,即/*.....*/

/*This is to print the output
data*/
proc print data=sashelp.cars;
run;
/*Creating dataset*/
data abc;
set xyz;
run;
Run Code Online (Sandbox Code Playgroud)

Luc*_*ini 22

我想我找到了一个简单的解决方案!

cpp -P yourcommentedfile.txt 
Run Code Online (Sandbox Code Playgroud)

一些更新:

来自用户ilkachu的引用(来自用户评论的原文):

我玩了一些 gcc 的选项:-fpreprocessed将禁用大多数指令和宏扩展(显然除了 #define 和 #undef )。添加-dD也会留下定义;并且std=c89可用于忽略新样式 // 注释。即使使用它们,cpp 也会用空格替换注释(而不是删除它们),并折叠空格和空行。

但是我认为在大多数情况下它仍然是合理且简单的解决方案,如果您禁用宏扩展和其他东西,我认为您会得到很好的结果...... - 是的,您可以将其与 shell 脚本结合起来以获得更好的效果... 以及更多...

  • 但是 `cpp` 将做的不仅仅是删除注释(处理 `#include`,扩展宏,包括内置的......) (14认同)
  • @LucianoAndressMartini,不,`tail -n +7` 只会删除前 7 行,它不会阻止 `#include` 处理或宏扩展。试试`echo __LINE__ | 例如 cpp`。或者`echo '#include /dev/zero' | cpp` (3认同)
  • 我玩了一些 gcc 的选项:`-fpreprocessed` 将禁用大多数指令和宏扩展(显然除了 `#define` 和 `#undef`)。添加`-dD`也会留下定义;并且 `std=c89` 可用于忽略新样式的 `//` 注释。即使使用它们,`cpp` 也会用空格替换注释(而不是删除它们),并折叠空格和空行。 (3认同)
  • 如果你这样做,你可能想使用 `-P` 模式。(这可能会消除使用 `tail` 的需要。) (2认同)

Sté*_*las 11

我曾经想出这个我们可以改进为:

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'
Run Code Online (Sandbox Code Playgroud)

处理更多的极端情况。

请注意,如果您删除评论,您可以更改代码的含义(1-/* comment */-1就像1 - -1while解析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=c99gcc -std=c11或添加的-trigraphs选项)。

它也适用于这个 C99/C11(非 ANSI/C90)代码:

// 评论
/\
/ 评论
// 多行\
评论
"// 不是评论"

(与gcc -E/ gcc -std=c99 -E/比较gcc -std=c11 -E

ANSI C 不支持// formof 注释。//否则在 ANSI C 中无效,因此不会出现在那里。一种//可能真正出现在 ANSI C 中的人为情况(如那里所述,您可能会发现其余的讨论很有趣)是使用stringify运算符时。

这是一个有效的 ANSI C 代码:

#define s(x) #x
s(//not a comment)
Run Code Online (Sandbox Code Playgroud)

而在 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*/$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"
Run Code Online (Sandbox Code Playgroud)

如果您的 GNUsed太旧而无法支持-E-z,您可以将第一行替换为:

sed -r ":1;\$!{N;b1}
Run Code Online (Sandbox Code Playgroud)


Bab*_*aba 6

sed

更新

/\/\*/ {
    /\*\// {
        s/\/\*.*\*\///g;
        b next
    };

    :loop;
    /\*\//! {
        N;
        b loop
    };
    /\*\// {
        s/\/\*.*\*\//\n/g
    }
    :next
}
Run Code Online (Sandbox Code Playgroud)

支持所有可能的(多行注释,[或和]之前的数据,,);

 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
-------------------
Run Code Online (Sandbox Code Playgroud) 跑:
$ sed -f command.sed FILENAME

e1
-------------------
e1e2
-------------------
e2
-------------------
e1

-------------------
e1
e2
-------------------

e2
-------------------
e1

-------------------
e1
e2
-------------------

e2
-------------------
Run Code Online (Sandbox Code Playgroud)


小智 2

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

给你:

sed 's/\*\//\n&/g' test | sed '/\/\*/,/\*\//d'

注意这在 OS X 上不起作用,除非你安装了gnu-sed. 但它可以在 Linux 发行版上运行。