我有很多关于Markdown格式编程的文章。有一个构建过程能够将这些文本转换为Word / HTML,并执行简单的验证规则,如拼写检查或检查文档是否具有所需的标题结构。我想扩展该构建代码,以检查所有文本中的复制粘贴或类似块。
是否有任何现有的Java / Groovy库可以帮助我进行分析?
我的第一个想法是使用PMD的CopyPasteDetector,但它太过分析以分析实际代码。我不知道如何用它来分析普通文本。
答案 0 :(得分:2)
你可能想尝试Dude,我自己的快速和脏的文本文件复制检测器。除了快速估计两个文本文件之间的共享量之外,它还可以确定一组文件之间的复制,绘制一个很好的共享关系图。
答案 1 :(得分:1)
您可以从两个字符串的简单实现Longest Common Substring (LCS)算法开始。查看一个Java implementation。
接下来,您可以看到Suffix Arrays和Genetics and string algorithms。
答案 2 :(得分:1)
毕竟我最终使用CPD和Groovy。如果有人感兴趣的话,这是代码:
import net.sourceforge.pmd.cpd.Tokens
import net.sourceforge.pmd.cpd.TokenEntry
import net.sourceforge.pmd.cpd.Tokenizer
import net.sourceforge.pmd.cpd.CPDNullListener
import net.sourceforge.pmd.cpd.MatchAlgorithm
import net.sourceforge.pmd.cpd.SourceCode
import net.sourceforge.pmd.cpd.SourceCode.StringCodeLoader
import net.sourceforge.pmd.cpd.SimpleRenderer
// Prepare empty token data.
TokenEntry.clearImages()
def tokens = new Tokens()
// List all source files with text.
def source = new TreeMap<String, SourceCode>()
new File('.').eachFile { file ->
if (file.isFile() && file.name.endsWith('.txt')) {
def analyzedText = file.text
def sourceCode = new SourceCode(new StringCodeLoader(analyzedText, file.name))
source.put(sourceCode.fileName, sourceCode)
analyzedText.eachLine { line, lineNumber ->
line.split('[\\W\\s\\t\\f]+').each { token ->
token = token.trim()
if (token) {
tokens.add(new TokenEntry(token, sourceCode.fileName, lineNumber + 1))
}
}
}
tokens.add(TokenEntry.getEOF())
}
}
// Run matching algorithm.
def maxTokenChain = 15
def matchAlgorithm = new MatchAlgorithm(source, tokens, maxTokenChain, new CPDNullListener())
matchAlgorithm.findMatches()
// Produce report.
matchAlgorithm.matches().each { match ->
println " ========================================"
match.iterator().each { mark ->
println " DUPLICATION ERROR: <${mark.tokenSrcID}:${mark.beginLine}> [DUPLICATION] Found a ${match.lineCount} line (${match.tokenCount} tokens) duplication!"
}
def indentedTextSlice = ""
match.sourceCodeSlice.eachLine { line ->
indentedTextSlice += " $line\n"
}
println " ----------------------------------------"
println indentedTextSlice
println " ========================================"
}