从字符串中删除单行和多行注释


19

目标

使用您选择的编程语言,编写最短的程序以消除代表C程序的字符串中的注释。


输入项

字符串可以视为任何形式的输入,但也可以视为变量。


使用说明

两种不同的注释将被删除:

  • 多行注释,以开头/*和结尾*/
  • 单行注释//以Linux样式的换行符(LF,\n)开始和结束

字符串中的注释不可删除。出于此挑战的目的,您只需要考虑- "分隔的字符串。特别是,您可以忽略使用- '分隔字符文字的可能性。您也可以忽略三边形和连字号(/\<LF>*...)。


例子

输入:

#include <stdio.h>

int main(int argc, char** argv)
{
    // this comment will be removed
    if (argc > 1) {
        printf("Too many arguments.\n");   // this too will be removed
        return 1;
    }
    printf("Please vist http://this.will.not.be.removed.com\n");
    printf("/* This will stay */\n");
    printf("\"/* This will stay too */\"\n");
    printf("//and so will this\\");
    // but not this
    printf("just \"ano//ther\" test.");
    return 0;
}

输出:

#include <stdio.h>

int main(int argc, char** argv)
{

    if (argc > 1) {
        printf("Too many arguments.\n");   
        return 1;
    }
    printf("Please vist http://this.will.not.be.removed.com\n");
    printf("/* This will stay */\n");
    printf("\"/* This will stay too */\"\n");
    printf("//and so will this\\");

    printf("just \"ano//ther\" test.");
    return 0;
}

输入:

/*
    this shall disappear
*/
#include <string>
int main(int argc, char** argv)
{
    string foo = ""/*remove that!**/;
    // Remove /* this
    int butNotThis = 42;
    // But do */ remove this
    int bar = 4 /*remove this*/* 3; // but don't remove that 3. */
    return 0;//just a comment
}/*end of the file has been reached.*/

输出:

#include <string>
int main(int argc, char** argv)
{
    string foo = "";

    int butNotThis = 42;

    int bar = 4 * 3; 
    return 0;
}

1
从哪里printf("\"/* This will stay too */\"\n");出现的应该成为代码?
manatwork

糟糕,抱歉...这只是一个错字。感谢您的关注!
Mathieu Rodic

空格算吗?前面有4个空格// this comment will be removed就消失了。有什么规则吗?
manatwork

1
我不太熟悉所列出的任何一种语言,因此某种形式的独立规范可能会很好,还有更多示例。
Zgarb

@manatwork:空格删除不是强制性的
Mathieu Rodic

Answers:


11

视网膜,35 +1 + 2 = 38字节

该程序包含两个文件,因此我为第二个文件添加了1个字节的罚款

//.*|/\*[\s\S]*?\*/|("(\\.|[^"])*")
$1

这是使用.NET风格的简单正则表达式替换(尽管在大多数其他风格中也可以使用)。

想法是同时匹配注释和字符串,但如果匹配是字符串,则只写回匹配项。通过显式匹配字符串,搜索注释时将跳过它们。


1
这在PHP中的效果出奇地好:regex101.com/r/kB5kA4/1
Ismael Miguel

1
@IsmaelMiguel是的,我没有使用任何特定功能。我选择.NET的唯一原因是因为Retina允许我编写仅用于正则表达式的程序,而无需调用诸如之类的任何开销preg_replace
Martin Ender

我对此很清楚。您已经使用了很多次。如果我没错,它是您创建的。这是出于好奇。而且,您现在拥有一个测试套件,可以在其中测试此问题引起的任何变化(我预计很多)
Ismael Miguel 2015年

真好!该正则表达式甚至可以与其他编程语言一起使用(当斜杠被转义时)。
Mathieu Rodic

我使用了您的正则表达式技术来改善了与我合作的第三方库:Dojo Toolkit
mbomb007 '18

15

Shell + coreutils + gcc编译器集合,31个字节

这个答案似乎有点漏洞,但是我没有看到任何明确禁止该问题的东西。

与其使用笨拙的正则表达式,不如使用为该工作而构建的工具。给出正确的结果应该没有问题:

cpp -fpreprocessed -o- -|sed 1d

接收来自STDIN的输入并输出到STDOUT。通常,ccp它将执行所有预处理(头文件,宏扩展,注释删除等),但是使用该-fpreprocessed选项,它将跳过大多数步骤,但仍将删除注释。此外,cpp # 1 "<stdin>"在输出的开头添加了一行,因此sed可以删除它。


1
“-fpreprocessed是隐含如果输入文件具有扩展名之一.i.ii.mi”。也许可以通过将文件保存为类似的形式a.i而不使用标志来节省一些字节?
Martin Ender

@MartinBüttner是的,我在手册中也注意到了这一点。因此,我希望有类似的东西cat>i.i;cpp -o- i.i|sed 1d。但是会进行完整的预处理(例如,插入stdio.h的完整内容)。可能的gcc错误???好吧,也许等我收到Mo'后再检查cpp来源。
Digital Trauma 2015年

|sed 1d如果添加-P选项,则可以删除。请注意(如问题所允许),因为它需要预处理的代码,所以无法正确处理三字组或行连续。
sch 2016年

3

Java 365

String a(String s){String o="";int m=1;for(int i=0;i<s.length();i++){String u=s.substring(i,Math.min(i+2,s.length()));char c=s.charAt(i);switch(m){case 1:m=u.equals("/*")?5:u.equals("//")?4:c=='"'?3:1;break;case 3:m=c=='"'?1:c=='\\'?2:3;break;case 2:m=3;break;case 4:m=c=='\n'?1:4;continue;case 5:m=u.equals("*/")?1:5;i+=m==1?1:0;continue;}o+=m<4?c:"";}return o;}}

不打高尔夫球

public static final int DEFAULT = 1;
public static final int ESCAPE = 2;
public static final int STRING = 3;
public static final int ONE_LINE_COMMENT = 4;
public static final int MULTI_LINE_COMMENT = 5;

String clear(String s) {
    String out = "";
    int mod = DEFAULT;
    for (int i = 0; i < s.length(); i++) {
        String substring = s.substring(i, Math.min(i + 2 , s.length()));
        char c = s.charAt(i);
        switch (mod) {
            case DEFAULT: // default
                mod = substring.equals("/*") ? MULTI_LINE_COMMENT : substring.equals("//") ? ONE_LINE_COMMENT : c == '"' ? STRING : DEFAULT;
                break;
            case STRING: // string
                mod = c == '"' ? DEFAULT : c == '\\' ? ESCAPE : STRING;
                break;
            case ESCAPE: // string
                mod = STRING;
                break;
            case ONE_LINE_COMMENT: // one line comment
                mod = c == '\n' ? DEFAULT : ONE_LINE_COMMENT;
                continue;
            case MULTI_LINE_COMMENT: // multi line comment
                mod = substring.equals("*/") ? DEFAULT : MULTI_LINE_COMMENT;
                i += mod == DEFAULT ? 1 : 0;
                continue;
        }
        out += mod < 4 ? c : "";
    }

    return out;
}

2

Python2- 163 134字节

import re
def f(s):
 for x in re.findall(r'("[^\n]*"(?!\\))|(//[^\n]*$|/(?!\\)\*[\s\S]*?\*(?!\\)/)',s,8):s=s.replace(x[1],'')
 print s

如您所见,正则表达式由2个交替的捕获组组成。第一个捕获所有引用的字符串。第二个全部评论。

我们需要做的就是删除第二组捕获的所有内容。

例:

Python 2.7.9 (default, Dec 11 2014, 04:42:00) 
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> def f(s):
...  for x in re.findall(r'("[^\n]*"(?!\\))|(//[^\n]*$|/(?!\\)\*[\s\S]*?\*(?!\\)/)',s,8):s=s.replace(x[1],'')
...  print s
... 
>>> code = r'''#include <stdio.h>
... 
... int main(int argc, char** argv)
... {
...     // this comment will be removed
...     if (argc > 1) {
...         printf("Too many arguments.\n");   // this too will be removed
...         return 1;
...     }
...     printf("Please vist http://this.will.not.be.removed.com\n");
...     printf("/* This will stay */\n");
...     printf("\"/* This will stay too */\"\n");
...     printf("//and so will this\\");
...     // but not this
...     printf("just \"ano//ther\" test.");
...     return 0;
... }
... /*
...     this shall disappear
... */
... #include <string>
... int main(int argc, char** argv)
... {
...     string foo = ""/*remove that!**/;
...     // Remove /* this
...     int butNotThis = 42;
...     // But do */ remove this
...     int bar = 4 /*remove this*/* 3; // but don't remove that 3. */
...     return 0;//just a comment
... }/*end of the file has been reached.*/'''
>>> f(code)
#include <stdio.h>

int main(int argc, char** argv)
{

    if (argc > 1) {
        printf("Too many arguments.\n");   
        return 1;
    }
    printf("Please vist http://this.will.not.be.removed.com\n");
    printf("/* This will stay */\n");
    printf("\"/* This will stay too */\"\n");
    printf("//and so will this\\");

    printf("just \"ano//ther\" test.");
    return 0;
}

#include <string>
int main(int argc, char** argv)
{
    string foo = "";

    int butNotThis = 42;

    int bar = 4 * 3; 
    return 0;
}

1

Rebol-151

f: func[t][Q:{"}W: complement charset Q parse t[any[[Q any["\\"|"\"Q | W]Q]|[a:[["//"to[lf | end]]|["/*"thru"*/"]]b:(remove/part a b):a skip]| skip]]t]

取消高尔夫+一些注释:

f: func [t] [
    Q: {"}
    W: complement charset Q     ;; any char thats not a double quote

    ; rule to parse t (c program) - it can be ANY of 
    ;     1. string 
    ;     2. OR comment (if so then remove)
    ;     3. OR pass thru

    parse t [
        any [
            ;; 1. String rule
            [Q any ["\\" | "\" Q | W] Q]

            ;; 2. OR comments rule
            | [
                a:  ;; mark beginning of match
                [
                    ;;    // comment    OR  /* comment */
                    ["//" to [lf | end]] | ["/*" thru "*/"]
                ]
                b:  ;; mark end of match 
                (remove/part a b) :a skip   ;; remove comment
            ]

            ;; 3. OR allow thru (so not a String or Comment)
            | skip
        ]
    ]

    t
]

1

的PHP

将@Martin Ender的答案转换为php:

$str = preg_replace_callback('/\/\/.*|\/\*[\s\S]*?\*\/|("(\\.|[^"])*")/m', 
  function($matches){
     if(\is_array($matches) && (\count($matches) > 1)){
        return $matches[1];
     }else{
        return '';
     }
  }, $str);

现在$str丢失了单行和多行注释。这对于在馈入之前剥离JSON数据中的注释很有用json_decode()


也许您可以通过使用三元运算符来减少字节数?
Mathieu Rodic

0

C#(262个字符):

从这个非常好的SO答案:

string a(string i){return Regex.Replace(i, @"/\*(.*?)\*/|//(.*?)\r?\n|""((\\[^\n]|[^""\n])*)""|@(""[^""]*"")+", m => { var v = m.Value; if (v.StartsWith("/*") || v.StartsWith("//")) return v.StartsWith("//") ? "\r\n" : ""; return v; }, RegexOptions.Singleline);

-1

JS(ES6),47个字符(WIP)

演示:http : //codepen.io/anon/pen/dPEMro

a=b=>b.replace(/(\/\*[^]*?\*\/|\/\/.*)\n?/g,"")

受到我的代码简化器的启发:http ://xem.github.io/miniMinifier/

尚不处理字符串中的注释...

我很好奇,看看是否有可能在JS正则表达式中实现这一目标。


如果此答案不符合要求,则应将其固定或删除。
mbomb007 '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.