ลบบรรทัดเดียวและความคิดเห็นหลายบรรทัดจากสตริง


19

เป้าหมาย

ใช้ภาษาการเขียนโปรแกรมที่คุณเลือกเขียนโปรแกรมที่สั้นที่สุดเพื่อกำจัดความคิดเห็นจากสตริงที่แทนโปรแกรม C


อินพุต

สตริงสามารถนำมาเป็นรูปแบบของการป้อนข้อมูลใด ๆ แต่ก็อาจถูกนำมาเป็นตัวแปร


คำแนะนำ

ความคิดเห็นที่แตกต่างกันสองประเภทจะถูกลบออก:

  • ความคิดเห็นหลายบรรทัดเริ่มต้นด้วย/*และลงท้ายด้วย*/
  • ความคิดเห็นบรรทัดเดียวเริ่มต้นด้วย//และลงท้ายด้วยตัวแบ่งบรรทัดสไตล์ Linux (LF, \n)

ความคิดเห็นภายในสตริงจะไม่ถูกลบ สำหรับจุดประสงค์ของการท้าทายนี้คุณจะต้องพิจารณา"สตริงที่ถูก จำกัด โดยเฉพาะอย่างยิ่งคุณสามารถเพิกเฉยต่อความเป็นไปได้ของ'ตัวอักษรที่ถูก จำกัด ตัวอักษร นอกจากนี้คุณยังสามารถละเว้น Trigraphs และการดำเนินการต่อเนื่องของบรรทัด ( /\<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");ปรากฏในควรเป็นรหัส?
จัดการ

โอ๊ะโอขออภัย ... มันเป็นเพียงแค่พิมพ์ผิด ขอบคุณที่สังเกต!
Mathieu Rodic

ช่องว่างนับรวมหรือไม่? ด้านหน้ามีที่ว่าง 4 แห่ง// this comment will be removedซึ่งเพิ่งหายไป มีกฎอะไรบ้าง?
จัดการ

1
ฉันไม่รู้ภาษาใด ๆ ในรายการที่ดีดังนั้นข้อมูลจำเพาะที่มีในตัวเองบางอย่างน่าจะดีพร้อมกับตัวอย่างเพิ่มเติม
Zgarb

@ การทำงาน: การลบช่องว่างไม่ได้รับคำสั่ง
Mathieu Rodic

คำตอบ:


11

เรติน่า , 35 + 1 + 2 = 38 ไบต์

โปรแกรมนี้ประกอบด้วยสองไฟล์จึงเราได้รวมโทษ 1 ไบต์สำหรับแฟ้มที่สอง

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

นี่คือการแทนที่ regex อย่างง่ายโดยใช้. NET flavours (แม้ว่ามันจะทำงานได้เหมือนกันในรสชาติอื่น ๆ ส่วนใหญ่)

แนวคิดคือจับคู่ทั้งความคิดเห็นและสตริง แต่เขียนเฉพาะการจับคู่ย้อนกลับหากเป็นสตริง โดยการจับคู่สตริงอย่างชัดเจนพวกเขาจะถูกข้ามเมื่อค้นหาความคิดเห็น


1
มันใช้งานได้ดีอย่างน่าประหลาดใจใน PHP: regex101.com/r/kB5kA4/1
Ismael Miguel

1
@IsmaelMiguel ใช่ฉันไม่ได้ใช้คุณลักษณะเฉพาะใด ๆ เหตุผลเดียวที่ฉันหยิบ NET เป็นเพราะ Retina ช่วยให้ฉันไปโปรแกรม regex preg_replaceเท่านั้นเขียนโดยไม่ต้องค่าใช้จ่ายของการเรียกสิ่งที่ต้องการใด
Martin Ender

ฉันรู้เรื่องนั้น คุณเคยใช้มันค่อนข้างมากมาก่อน ถ้าฉันถูกต้องมันถูกสร้างขึ้นโดยคุณ มันเป็นสิ่งที่อยากรู้อยากเห็น และตอนนี้คุณมีชุดทดสอบที่คุณสามารถทดสอบการเปลี่ยนแปลงใด ๆ ก็ตามที่เกิดขึ้นในคำถามนี้ (ฉันทำนายหลาย ๆ ข้อ)
Ismael Miguel

ดี! นิพจน์ทั่วไปนี้ใช้งานได้กับภาษาการเขียนโปรแกรมอื่น (เมื่อสแลชถูกหลบหนี)
Mathieu Rodic

ฉันใช้เทคนิค regex ของคุณเพื่อปรับปรุงห้องสมุดบุคคลที่สามที่ฉันทำงานด้วย: Dojo Toolkit
mbomb007

15

การรวบรวมคอมไพเลอร์คอมไพเลอร์ Shell + coreutils + gcc ขนาด 31 ไบต์

คำตอบนี้อาจดูเหมือน loopholey เล็กน้อย แต่ฉันไม่เห็นสิ่งใดที่ห้ามโดยเฉพาะในคำถาม

แทนที่จะใช้นิพจน์ทั่วไปที่เงอะงะทำไมไม่ใช้เครื่องมือที่สร้างขึ้นสำหรับงาน ไม่ควรมีปัญหาในการให้ผลลัพธ์ที่ถูกต้อง:

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 ที่เป็นไปได้ ??? บางทีฉันอาจจะตรวจสอบแหล่ง cpp เมื่อฉันได้รับ mo '
บาดเจ็บทางดิจิตอล

คุณสามารถลบได้|sed 1dหากคุณเพิ่ม-Pตัวเลือก โปรดทราบว่า (ตามที่ได้รับอนุญาตจากคำถาม) เนื่องจากคาดว่ารหัสที่ประมวลผลล่วงหน้าจะไม่จัดการกับ trigraphs หรือการต่อเนื่องของสายอย่างถูกต้อง
sch

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;}}

Ungolfed

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

อย่างที่คุณเห็นที่นี่ regex ประกอบด้วยกลุ่มจับภาพสลับกัน 2 กลุ่ม คนแรกจับทุกสตริงที่ยกมา ประการที่สองหนึ่งความคิดเห็นทั้งหมด

สิ่งที่เราต้องทำคือลบทุกสิ่งที่กลุ่มที่ 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]

Ungolfed + คำอธิบายประกอบบางส่วน:

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 ตัวอักษร):

จากนี้ดีมากดังนั้นคำตอบ:

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)

DEMO: http://codepen.io/anon/pen/dPEMro

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

แรงบันดาลใจจาก minifiers codegolfed ของฉัน: http://xem.github.io/miniMinifier/

ยังไม่ได้จัดการความคิดเห็นในสตริง ...

ฉันอยากรู้ว่าเป็นไปได้หรือไม่ที่จะประสบความสำเร็จใน JS regexes


หากคำตอบนี้ไม่ตรงตามข้อกำหนดก็ควรจะแก้ไขหรือลบ
mbomb007
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.