代码之家  ›  专栏  ›  技术社区  ›  PeterK

识别(程序设计)语言的关键字

  •  4
  • PeterK  · 技术社区  · 15 年前

    Code for identifying programming language in a text file ). 我真的很感谢我得到的所有答案,这对我帮助很大。

    我使用的方法如下:我有一个“学习”perl脚本,它通过对一组示例文件进行单词直方图来识别语言中最常用的单词。这些数据然后由c++程序加载,然后c++程序检查给定的文本并根据找到的单词累计每种语言的分数,然后简单地检查哪种语言的分数最高。

    现在我想把它做得更好,在鉴定的质量上做一点工作。 (许多语言的分数都很小,但没有比我的门槛更高的了)。经过一些调试,研究等我发现,这可能是因为事实上,所有的字都被认为是平等的。这意味着,例如看到一个“#include”与看到一个“while”具有相同的效果——两者都表明它可能是c/c++(我现在忽略了“while”在许多其他语言中使用的事实),但当然在更大的.cpp文件中可能有大量的“while”,但大多数时候只有少数几个“#include”。

    所以“#include”更重要的事实被忽略了,因为我想不出一个好方法来确定一个词是否比另一个词更重要。 现在请记住,创建数据的脚本是相当愚蠢的,它只是一个单词直方图,并且为每个选中的单词指定一个1分。它甚至不看单词(所以如果有“#&|”的话?/“在一个文件中,它经常被选为一个好词)。

    另外,我想有数据创建部分完全自动化,所以没有人应该看看数据,改变他们,改变分数,改变文字等所有的“脑筋”应该在脚本和cpp程序。

    注:谢谢所有费心回答的人,你帮了我很多。

    我的这方面的工作几乎完成了,所以我将描述我做了什么,以获得良好的结果。

    1) 得到一个像样的训练集,每种语言大约30-50个文件,来自不同的来源,以避免编码风格的偏见
    2) 编写一个perl脚本来实现单词直方图。实施黑名单和白名单(详情见下文)

    4) 为每种语言添加大约五个最重要的单词到白名单中。这些词可以在给定语言的大多数源代码中找到,但频率不足以进入直方图。例如,对于C/C++,我在白名单中有:包括,定义,α,IFIFF,α,IFNDEF和α-Endif。
    5) 强调文件的开头,所以在前50-100行中找到的单词要多加分数
    6) 在执行单词直方图时,使用 @words = split(/[\s\(\){}\[\];.,=]+/, $_); 这对我认为的大多数语言都是可以的(给我最好的结果)。对于每种语言,在最终结果中有大约10-20个最常用的单词。

    8) 编写一个程序,用与脚本相同的方式处理文本文件-使用相同的规则标记化。如果在柱状图数据中找到一个单词,请在正确的语言中添加点。直方图中只对应一种语言的单词应该加更多的点,属于多种语言的单词应该加更少的点。

    欢迎评论。目前,在大约1000个文本文件中,我得到了80个未知信息(主要是非常短的文件,主要是只有一两行的javascript)。大约有20个文件被认错了。文件大小约为11kB,范围从100字节到100KB(总计约11MB)。一秒钟就能处理完,这对我来说已经足够了。

    4 回复  |  直到 8 年前
        1
  •  3
  •   MSalters    15 年前

    我认为你从错误的角度来看待这个问题。从你的描述来看,听起来你在建造一个 分级机 . 一个好的分类器需要区分不同的类;它不需要精确地估计输入和最可能的类之间的对应关系。

    实际上:你的分类器不需要精确地评估C++的某个输入的接近程度,它只需要确定输入是否更像C而不是C++。这让你的工作变得容易多了——你目前的大多数“未知”案例将接近一种或两种语言,即使它们没有超过你的基本门槛。

    现在,一旦您意识到这一点,您还将看到您的分类器需要什么:不是样本文件的一些随机方面,而是将两种语言区分开来的原因。因此,当您解析了C样本和C++样本时,您将看到 #include class template #包括 区分C++和java。

    { ; // , /* ' -- , # ! 因为伪关键字会有帮助。

    这还标识了另一个分类规则:SQL通常具有 -- 在一行的开头,而在C中它通常出现在其他地方。因此,分类器考虑上下文也可能很有用。

        2
  •  2
  •   Sebastian    15 年前

    使用谷歌代码搜索来学习关键词集的权重:C++中包含的672个命中,在Python中只有5000个。

    您可以通过查看语言的结果总数来规范化结果: C++提供了大约770个文件,而Python返回了120个文件。

    因此,“y-包含”在Python文件中非常罕见,但几乎存在于所有C++文件中。(当然,现在你仍然需要学习区分C++和C。)剩下的就是对概率进行正确的推理。

        3
  •  1
  •   Martin Hennings    15 年前

    您需要在查找数据中获得一些独占性。
    当教授您期望的编程语言时,您应该搜索一种或几种语言的典型单词。如果一个单词出现在同一语言的多个代码文件中,但很少或根本没有出现在其他语言文件中,这是对该语言的强烈建议。
    因此,一个单词的分数可以在查找端通过选择一种语言或一组语言所独有的单词来计算。从这些单词中找出几个,然后把分数相加得到它们的交集,然后找到你的语言。

        4
  •  0
  •   Greg Bacon    15 年前

    在回答你的另一个问题时,有人推荐了一个 naïve Bayes classifier . 你应该执行这个建议,因为这项技术善于根据不同的特征进行分离。你提到了 while 关键字,但这不太可能有用,因为有太多语言使用它,Bayes分类器不会将其视为有用的。

    问题的一个有趣部分是如何标记未知程序。以空格分隔的块是一个相当粗糙的开始,但要有意义地超越它将是一个棘手的问题。