【问题标题】:Using sed to show C style comment and C++ comment使用 sed 显示 C 风格注释和 C++ 注释
【发布时间】:2018-09-06 08:37:38
【问题描述】:

到目前为止,我这样做了,但它并没有打印出我想要的内容。先感谢您。

$  sed -n -e "/\(*\)/g" c_comments | sed -n '/\/\*/p; /^ \*/p' c_comments |sed -n '/[[:blank:]]/p' c_comments 

这是文本文件 c_cmets,我想提取 c_style 注释和 C++ cmets。 // 包含各种 C 和 C++ 样式 cmets 示例的文件

/* simple C style comment on one line with no code  */

x = 5*3;   /* Example comment following code   */

   /* comments do not have to begin at the line beginning  */
/*  And you can have empty comments like the next one */
/**/
/*  comments with code following the comment  (not possible with C++ style) 
*/  x = w * u/y/z;
  // As shown below you can have what appear to comments embedded in a 
 string
    // The line below should be counted as code
printf(" This output string looks like a /* comment */ doesn't it?\n"); 
/* ---- Example of a multiline 
C style comment  */       
c++;  //  C ++ style comment following code
c=a/b*c;   /*  comment between two pieces of code */   w = a*b/e;
 /*  This is a multiline c style comment.  This
comment covers several
lines.
 ------*/
a = b / c * d;
/* -----------End of the file ---------------*/ 

【问题讨论】:

  • 如果您将输入管道输入到sed,您不应该给它一个文件名参数。当它得到一个文件名参数时,它会忽略标准输入。
  • 您可以使用一个sed 命令和多个-e 选项来执行多个不同的操作。
  • C 和 C++ 都使用相同的注释样式。你觉得有什么区别?
  • 那么你的建议是什么?你的意思是只使用一次文件名吗
  • 请注意,sed 正则表达式可以帮助您找到一些 cmets,但不是全部。 C/C++ 语法是一类比正则表达式可以解析的更复杂的语言。 CS的人都知道理论上的解释。

标签: linux unix sed command-line stream


【解决方案1】:
sed -n -e '/^[[:space:]]*\/\//p' -e ' /^[[:space:]]*\/\*.*\*\/[[:space:]]*$/p' -e '/^[[:space:]]*$/p' c_comments

【讨论】:

    【解决方案2】:

    以下将处理您的特定文件。

    #! /bin/sed -f
    
    # using ':' for regex delimiter, as we are matching a lot of
    # literal '/' in the following expressions
    
    # remove quoted strings
    # TODO: allow quotes in comments and detect multiline quoted strings
    s:["][^"]*["]::g
    
    # detect '/* ... */'
    \:/\*.*\*/: {
        # handle leading '//'
        \://.*/\*: {
            s:.*//://:
            p;d
        }
        s:.*/\*:/*:
        s:\*/.*:*/:
        p;d
    }
    
    # detect '/* ... \n ... */'
    # TODO: fix the '// ... /*' case
    \:/\*:,\:\*/: {
        s:.*/\*:/*:
        s:\*/.*:*/:
        p;d
    }
    
    # detect //
    \://: {
        s:.*//://:
        p;d
    }
    d
    

    上面更多的是一个非示例而不是示例——展示一些在 sed 中真正难以做到的事情(特别注意TODO's) .

    因此,一般来说,使用单个 sed 脚本提取 C cmets 不太适合 IMO —— 让它完全正确会非常困难,而且结果很快就会演变成一些非常迟钝的代码。

    这是一个替代方案,用 sed 装饰我们的 C 源代码,使用 awk 对其进行过滤(考虑到多级 C 语法规则),然后删除再次使用 sed 进行装饰:

    c_decorate

    #! /bin/sed -f
    s:\r::g
    s:/\*:\rC/*:g
    s:\*/:*/\rE:g
    s://:\rL//:g
    s:":\rQ":g
    

    c_filter

    #! /usr/bin/awk -f
    BEGIN {
        RS = ORS = "\r"
        lc=0 # State variable for continuing a C++ style Line comment
        cc=0 # State variable for continuing a C style comment
        qt=0 # quote-count
    }
    
    NR == 1 { print ""; next }
    
    /^C/ { # Begin C-Style Comment
        if (qt % 2)
            next
        if (lc) {
            if ($0 ~ /\n/) {
                lc = 0
                sub(/\n.*/, "\n")
            }
        } else {
            cc = 1
        }
        print
        next
    }
    /^E/ { # End C-Style Comment
        if (qt % 2)
            next
        if (lc) {
            if ($0 ~ /\n/) {
                lc = 0
                sub(/\n.*/, "\n")
            }
            print 
        } else if (cc) {
            cc = 0
            if ($0 ~ /\n/)
                print "\n"
            else
                print "E"
        }
        next    
    }
    /^L/ { # Begin C++ Style Line Comment
        if (qt % 2)
            next
        if (!cc) {
            lc = 0
            if ($0 ~ /\n/)
                sub(/\n.*/, "\n")
            else
                lc = 1
        }
        print
        next
    }
    /^Q/ { # Quote
        if (lc || cc)
            print
        else
            qt++
        next
    }
    

    c_cleanup

    #! /bin/sed -f
    $ {
        /^$/ d
    }
    s:\r[CELQ]\?::g
    

    然后调用:

    $ c_decorate c_comments | c_filter | c_cleanup
    

    Awksed 更自然地适合过滤,因为它原生支持记录分隔符的更改,并且更容易指定和推理任意逻辑关系。

    为了摆脱评论标签,这里是 c_decorate 的替代版本:

    #! /bin/sed -f
    s:\r::g
    s:/\*:\rC:g
    s:\*/:\rE:g
    s://:\rL:g
    s:":\rQ":g
    

    更新 9/2019 (@Russ) 这似乎不能很好地处理 cmets 中的“引号”,或者嵌入在 C++ 单行 cmets 中的 C 样式 cmets,如

    //* this is not handled well.  
    /* nor "is" this. */
    

    因此,我将它用于 c_decorate:

    #! /bin/sed -f
    s:\r::g
    # trouble is //* first matches //, then matches /*
    s:[^/]/\*:\rC/*:g
    s:^/\*:\rC/*:g
    s:\*/:*/\rE:g
    s://\+:\rL&:g
    # does not handle quotes w/in comments
    # s:":\rQ":g
    

    【讨论】:

    • 这很好,但在某些“//”形式上会混淆。我认为它在注释中的 // 后跟双引号时失败,例如,//“foo”是我们想要的 - 在这种情况下,它会翻转一点并立即开始包含未注释的代码。
    猜你喜欢
    • 2012-07-28
    • 2010-12-17
    • 2011-03-20
    • 2017-12-24
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    相关资源
    最近更新 更多