Bash Linux:在四个不同的文件中搜索巧合
场景:四个文件,每个文件上有300行。我想知道这四个文件中哪些行仅使用bash(请不要使用perl/python/ruby) 快速样品 $cat bad_domains.urlvoid a b c d e $cat bad_domains.alienvault f g a c h $cat bad_domains.hphosts i j k a h $cat bad_domains.malwaredomain l b m f a jBash Linux:在四个不同的文件中搜索巧合,bash,search,Bash,Search,场景:四个文件,每个文件上有300行。我想知道这四个文件中哪些行仅使用bash(请不要使用perl/python/ruby) 快速样品 $cat bad_domains.urlvoid a b c d e $cat bad_domains.alienvault f g a c h $cat bad_domains.hphosts i j k a h $cat bad_domains.malwaredomain l b m f a j 优化我的代码有什么好的建议吗?我读了一些关于二分法搜索的
优化我的代码有什么好的建议吗?我读了一些关于二分法搜索的文章,可能会有用。如果每个文件中的行都是唯一的:
cat file1 file2 file3 file4 | sort | uniq -c | grep '^ *4 '
使用
comm
:
comm -12 <(awk 'FNR==NR{a[$0];next} $0 in a' f1 f2) <(awk 'FNR==NR{a[$0];next} $0 in a' f3 f4)
a
bash4.x(和ksh93)的comm-12
创建由其中一个文件(主文件)的行索引的关联数组
对于剩余的每个文件,创建第二个由文件行索引的数组(工作),然后在主文件上迭代
数组删除带有键的任何条目,该键不同时出现在工作数组中
处理后留在master[]中的任何密钥都必须位于所有文件中
list=( bad_domains.* )
typeset -A master
while IFS= read -r key ; do master[$key]=1 ; done < "${list[0]}"
unset list[0]
for file in "${list[@]}" ; do
typeset -A work
while IFS= read -r key ; do work[$key]=1 ; done < "$file"
for key in "${!master[@]}" ; do [[ ${work[$key]+set} = set ]] || unset master[$key] ; done
unset work
done
for key in "${!master[@]}" ; do printf '%s\n' "$key" ; done
list=(坏域。*)
打字机-母版
而IFS=读取-r键;do master[$key]=1;完成<“${list[0]}”
未设置列表[0]
对于“${list[@]}”中的文件;做
排版-作品
而IFS=读取-r键;做工作[$key]=1;完成<“$file”
对于“${!master[@]}”中的键;执行[${work[$key]+set}=set]| |取消设置主控[$key];完成
未完成的工作
完成
对于“${!master[@]}”中的键;不打印“%s\n”“$key”;完成
如果一行在同一个文件中有两次,但在另一个文件中没有两次,该怎么办?那么它将不起作用。这就是为什么我的答案以if.nop开头,文件之间的行不是唯一的,但提示是thx:)你有权不喜欢它。对我来说,这个评论毫无用处,因为你还没有告诉我们为什么。我认为这是一个很好的工具链示例。而且很容易修改格式。是的,这是一个很好的例子,但我想对于这种情况来说不是最好的工具。无论如何,干得好<代码>grep-f f1 f2与grep-f f3 f4
组合应使其。。。但我找不到办法。Anubhava的comm
似乎是最好的工具!很好的解决方案,我喜欢它,因为你不使用awk或sed,我会记住它的未来。无论如何,对于这个特殊的案例,我使用了第一个使用awk的解决方案,效果非常好。天哪,这是什么魔法,我已经从每次搜索+15分钟变为不到30秒!!!我不知道awk能够做这种搜索,非常感谢!!
awk 'FNR==NR{a[$0];next} $0 in a' <(awk 'FNR==NR{a[$0];next} $0 in a' f1 f2) <(awk 'FNR==NR{a[$0];next} $0 in a' f3 f4)
list=( bad_domains.* )
typeset -A master
while IFS= read -r key ; do master[$key]=1 ; done < "${list[0]}"
unset list[0]
for file in "${list[@]}" ; do
typeset -A work
while IFS= read -r key ; do work[$key]=1 ; done < "$file"
for key in "${!master[@]}" ; do [[ ${work[$key]+set} = set ]] || unset master[$key] ; done
unset work
done
for key in "${!master[@]}" ; do printf '%s\n' "$key" ; done