用于识别文本文件中的编程语言的代码 [关闭]

Posted

技术标签:

【中文标题】用于识别文本文件中的编程语言的代码 [关闭]【英文标题】:Code for identifying programming language in a text file [closed] 【发布时间】:2011-04-05 17:45:40 【问题描述】:

我应该编写代码,当给定一个文本文件(源代码)作为输入时,它将输出它是哪种编程语言。这是问题的最基本定义。更多约束如下:

我必须用 C++ 编写。 应识别多种语言 - htmlphp、perl、ruby、C、C++、Java、C#... 误报(错误识别)的数量应该很低 - 输出“未知”比输出错误结果更好。 (它将在概率列表中,例如未知:100%,见下文) 输出应该是代码知道的每种语言的概率列表,所以如果它知道 C、Java 和 Perl,输出应该是例如:C:70%,Java:50%,Perl:30%(请注意,概率总和不需要达到 100%) 它应该具有良好的准确性/速度比(速度更受青睐)

如果代码的编写方式可以很容易地添加新的语言进行识别,并且只需为该特定语言添加“设置/数据”,那就太好了。我可以使用任何可用的东西——启发式、神经网络、黑魔法。任何事物。我什至可以使用现有的解决方案,但是:解决方案必须是免费的、开源的并允许商业使用。它必须以易于集成的源代码或静态库的形式出现 - 没有 DLL。但是我更喜欢编写自己的代码或仅使用其他解决方案的片段,我厌倦了集成其他人的代码。最后一点:也许你们中的一些人会建议 FANN(快速人工神经网络库)——这是我唯一不能使用的东西,因为这是我们已经使用的东西,我们想要替换它。

现在的问题是:你会如何处理这样的任务,你会怎么做?有什么建议如何实现或使用什么?

编辑: 基于 cmets 和答案,我必须强调一些我忘记的事情:速度非常关键,因为这将获得数千个文件并且应该快速回答,所以看一千个文件最多应在几秒钟内为所有文件生成答案(文件的大小当然会很小,每个文件只有几 kB)。所以试图编译每一个是没有问题的。问题是,我真的想要每种语言的概率——所以我更想知道该文件可能是 C 或 C++,但它是 bash 脚本的机会非常低。由于代码混淆、cmets 等。我认为寻找 100% 准确的代码是一个坏主意,实际上不是这样做的目标。

【问题讨论】:

一个相当厚颜无耻的想法 - 通过每种语言的编译器运行它,然后选择不会出错的那个? ;)。 (是的,我知道 - 可能很慢,如果代码无法编译,或者用户正在编写 polygots 等,可能会完全出错。) +1:很好的问题。但我认为“概率”部分没有意义:输入在特定语言中要么是合法的,要么不是。我不明白它属于语言 A 的概率高于属于语言 B 的概率是什么意思。 polyglot programs 呢? 看到这里了吗? ***.com/questions/475033/… @Philip Potter:这是我想要概率的原因之一,而不是一个明确的答案。 【参考方案1】:

如果您知道源文件将符合标准,那么文件扩展名对于几乎每种语言都是唯一的。我假设您已经考虑过这一点,并根据其他一些信息排除了它。

如果您不能使用文件扩展名,最好的方法是找到语言之间最不同的东西并使用它们来确定文件类型。例如,for 循环语句语法在语言之间不会有太大差异,但包包含语句应该。如果你有一个包含 java.util.* 的文件,那么你就知道它是一个 java 文件。

【讨论】:

您无法以这种方式计算每种语言的概率。 想知道在 Brainf*** 或 Haskell 中的循环是什么样子的。 @Lieven 您不能仅根据我的建议来计算概率,但您当然可以有一个好的开始。如果您根据句法差异排除某些语言,则更容易确定概率。另外,如果您可以根据包含语句确定地识别语言,那么概率是不必要的。 +1 用于文件扩展名查询【参考方案2】:

我能想到的一个简单解决方案是,您可以只识别不同语言中使用的关键字。每个识别出的单词都会得分+1。然后计算比率=identified_words / total_words。得分最高的语言是获胜者。当然,还有一些问题,比如使用 cmets 等。但我认为这是一个非常简单的解决方案,应该适用于大多数情况。

【讨论】:

按照这个想法,你可以尝试一个朴素的贝叶斯分类器,比如早期的垃圾邮件过滤器。这样也能得到很好的结果? +1 为原始和评论 - 这是我所知道的获得快速且相当准确的性能的最佳方式。 我可以看到这种方法的唯一缺点是某些关键字对于某些语言比其他关键字更具特征。因此需要事先进行一些统计分析。但我可能会这样做,看起来效果很好。【参考方案3】:

您也许可以尝试考虑语言差异并使用二叉​​树对其进行建模,例如“是否找到了特征 X?”如果是,则朝一个方向前进,如果不是,则朝另一个方向前进。

通过有效地构建此搜索树,您可以以相当快的代码结束。

【讨论】:

并不是每个 Perl 程序都展示了 Perl 的所有特性。没有 Perl 特性 X 使得每个有效的 Perl 程序都具有 X。 那么你会发现通过排除其他可能性 那么perl程序会在二叉树中出现多次。因此,二叉树的大小不能保证为 O(logN)。【参考方案4】:

看看nedit。它有一个语法高亮识别系统,位于 Syntax Highlighting->Recognition Patterns 下。您可以浏览示例识别模式here,或下载程序并查看标准模式。

这是highlighting system的描述。

【讨论】:

unix 实用程序file 有它自己的一套启发式方法,尽管它们可能太简单了。 @dmckee,是的,但是对于非常短的程序,它会失败:/【参考方案5】:

这个速度不快,可能无法满足你的要求,只是一个想法。它应该易于实施,并且应该提供 100% 的结果。

您可以尝试使用不同的编译器/解释器(开源或免费)编译/执行输入文本,并在后台检查错误。

【讨论】:

如果它编译为一种以上的语言怎么办?例如。 nyx.net/~gthompso/poly/micah.txt 同时作为 C 和 perl 工作 然后你说 50% 的概率 C,50% - Perl。根据问题作者的说法,这是可以的。 没错。如果它编译了,那么谁能证明相反的呢?【参考方案6】:

由于预先知道语言列表,因此您知道每种语言的语法/语法。 因此,例如,您可以编写一个函数来从提供的源代码中提取保留字。

构建一个二叉树,其中包含您支持的所有语言的所有保留字。然后使用从上一步中提取的保留字遍历该树。

如果你最后只剩下一种可能性——这就是你的语言。 如果您过早结束程序 - 那么(从您停止的地方) - 您可以分析您在树上的位置,以确定哪些语言仍然是可能的。

【讨论】:

+1:这可能非常准确,但考虑到数千个文件,速度是否足够快? 谢谢阿克塞尔。您可能可以结合 2 个阶段:当您提取保留字时,立即将它们送入树中。在某些情况下,您会在到达输入源代码末尾之前检测语言方式。最慢的部分实际上是应用所有语言的语法规则(即需要构建大量 L 字符串等 - 这几乎就像为所有支持的语言编写解析器)【参考方案7】:

Sequitur 算法从终结符号序列中推断出上下文无关文法。也许您可以使用它与每种语言的一组已知生产规则进行比较。

【讨论】:

【参考方案8】:

您遇到document classification 的问题。我建议您阅读有关naive bayes classifiers 和support vector machines 的信息。在文章中有实现这些算法的库的链接,其中许多具有 C++ 接口。

【讨论】:

确实,我会说一个朴素贝叶斯分类器,在开始时快速检查明确的“必须是”单词(即 Python 或 Ruby env 行。)【参考方案9】:

很抱歉,如果您必须解析数千个文件,那么最好的办法是查看文件扩展名。不要过度设计一个简单的问题,或对简单的任务提出繁重的要求。

听起来您有数千个源代码文件,但您不知道它们是用什么编程语言编写的。您在什么样的编程环境中工作? (排除人为作业要求的可能性)我的意思是我始终可以依赖的软件工程基础之一是 c++ 代码文件具有 .cpp 扩展名,java 代码文件具有 .java 扩展名,c 代码文件有 .c 扩展名等...您的公司是否在使用这些标准时又快又松?如果是这样,我真的很担心。

【讨论】:

谁说他的“文件”甚至是有名字的文件?也许他正试图在 SO 之类的论坛上对代码 sn-ps 进行正确的语法突出显示。或者,他可能正试图找出某些代码文件的扩展名是否错误! 抱歉,这里不能依赖文件扩展名。无论如何感谢您的建议! 你想解决什么类型的问题?【参考方案10】:

正如 dmckee 建议的那样,您可能想看看 Unix file 程序,它的 source is available。该实用程序使用的启发式方法可能是一个很好的灵感来源。由于它是用 C 编写的,我猜它符合 C++ 的条件。 :) 但是,您不会直接获得置信百分比;也许它们在内部使用?

【讨论】:

以上是关于用于识别文本文件中的编程语言的代码 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

C语言如何判断文本文档的结束

Javascript / Jquery识别文本文档中的每一行[重复]

如何运行文本文档编程命令

关于“任意编码”的txt格式的文本文档“批量转换”为同一种编码的文本文件,要能自动识别源编码(200分)

在c语言中怎样打开一个文本文档

怎样用文本文档写命令脚本文件? 有例子最好