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