Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 优化重复检测 背景_Perl_Bash_Optimization_Big O_Code Duplication - Fatal编程技术网

Perl 优化重复检测 背景

Perl 优化重复检测 背景,perl,bash,optimization,big-o,code-duplication,Perl,Bash,Optimization,Big O,Code Duplication,这是一个优化问题。Oracle表单XML文件包含以下元素: <Trigger TriggerName="name" TriggerText="SELECT * FROM DUAL" ... /> sql/module=DIAL_ACCESS+trigger=KEY-LISTVAL+filename=d_access.fmb.sql sql/module=REP_PAT_SEEN+trigger=KEY-LISTVAL+filename=rep_pat_seen.fmb.s

这是一个优化问题。Oracle表单XML文件包含以下元素:

<Trigger TriggerName="name" TriggerText="SELECT * FROM DUAL" ... />
sql/module=DIAL_ACCESS+trigger=KEY-LISTVAL+filename=d_access.fmb.sql     
sql/module=REP_PAT_SEEN+trigger=KEY-LISTVAL+filename=rep_pat_seen.fmb.sql 
我编写了一个脚本,使用蛮力方法生成精确副本的列表

问题 有37497个文件可以相互比较;将一个文件与所有其他文件进行比较需要8分钟。从逻辑上讲,如果
A=B
A=C
,则无需检查
B=C
。所以问题是:如何消除冗余比较

脚本将在大约208天内完成

脚本源代码 比较脚本如下所示:

#!/bin/bash

echo Loading directory ...

for i in $(find sql/ -type f -name \*.sql); do
        echo Comparing $i ...

        for j in $(find sql/ -type f -name \*.sql); do
                if [ "$i" = "$j" ]; then
                        continue;
                fi

                # Case insensitive compare, ignore spaces
                diff -IEbwBaq $i $j > /dev/null

                # 0 = no difference (i.e., duplicate code)
                if [ $? = 0 ]; then
                        echo $i :: $j >> clones.txt
                fi
        done
done
问题: 如何优化脚本,使检查克隆代码的速度加快几个数量级

想法#1 将匹配的文件删除到另一个目录中,这样就不需要对它们进行两次检查

系统约束 使用带SSD的四核CPU;尽可能避免使用云服务。该系统是一台安装了Cygwin的基于Windows的机器——欢迎使用其他语言的算法或解决方案


谢谢大家!

要优化文件的比较,请执行以下操作:

#!/bin/bash

for i; do
    for j; do
        [[ "$i" != "$j" ]] &&
            if diff -IEbwBaq "$i" "$j" > /dev/null; then
                echo "$i & $j are the same"
            else
                echo "$i & $j are different"
            fi
    done
done
用法

./script /dir/*

您的解决方案和sputnick的解决方案都需要O(n^2)时间。这可以通过对文件进行排序并使用列表合并在O(nlogn)时间内完成。通过比较文件的MD5(或任何其他加密强哈希函数),而不是文件本身,可以进一步加快速度

假设您在
sql
目录中:

md5sum * | sort > ../md5sums
perl -lane 'print if $F[0] eq $lastMd5; $last = $_; $lastMd5 = $F[0]' < ../md5sums
md5sum*| sort>。/md5sum
perl-lane'如果$F[0]eq$lastMd5打印$last=$\u0$lastMd5=$F[0]'<../md5sums

使用上述代码将只报告精确的逐字节重复。如果你想考虑两个不相同的文件以达到这个比较的目的(例如,如果你不关心情况),首先创建一个规范化的每个文件的拷贝(例如,通过将每个字符转换成小写,使用<代码> Tr.AZ z -Z z Outfile )。然后用一套。我不确定bash是否可以做到这一点,但python可以做到。虽然如果你想要最好的性能,C++是前进的方向。

两个初始问题:1)“重复”文件中的数据总是相同的顺序,还是线可能出现故障?我假设是前者,因为您使用的是
diff
;2) 要将其视为重复,我们是否可以假定它必须区分大小写?我假设不区分大小写,因为您专门将
diff
与不区分大小写的比较一起使用-但是如果它区分大小写,则存在更好的方法。1)文件应以相同的顺序返回;这可以通过使用排序命令或参数
查找
来强制执行。2) 案件需要无意识地匹配;只有空格和空行不同的文件必须被视为重复代码。如果您想要性能,bash脚本不是一个好主意。bash不是问题所在,Dani(虽然我同意基于C的解决方案执行速度会更快,但即使比较所有37000个文件只需30秒[而不是8分钟],这仍然需要12天)。该算法在任何语言中都是
O(n^2)
cmp
不提供不区分大小写或忽略空白的比较。必须忽略大小写和空白。关于散列的好主意;我还想简单地将匹配的文件移动到另一个目录。可以使用
tr-d'\r\n\t'
删除空白。谢谢!我用
tr-s
挤压它。