Noob在这里。
如果列表中存在父域,我试图通过删除所有子域来削减域列表。我已经成功地拼凑了一个脚本,在经过一些搜索和阅读之后,它会在PowerShell中做到这一点。输出不是我想要的,但可以正常工作。我的解决方案的问题是,由于我的初始列表(数万个条目)的大小,它需要很长时间才能运行。
更新:我已更新我的示例以澄清我的问题。
示例“parent.txt”列表:
adk2.co
adk2.com
adobe.com
helpx.adobe.com
manage.com
list-manage.com
graph.facebook.com
示例输出“repeats.txt”文件:
adk2.com (different top level domain than adk2.co but that's ok)
helpx.adobe.com
list-manage.com (not subdomain of manage.com but that's ok)
然后,我将从父项中删除重复项,并留下“唯一”子域和域列表。我在一个单独的脚本中有这个。
使用我当前脚本的最终列表示例:
adk2.co
adobe.com
manage.com
graph.facebook.com (it's not facebook.com because facebook.com wasn't in the original list.)
理想的最终名单:
adk2.co
adk2.com (since adk2.co and adk2.com are actually distinct domains)
adobe.com
manage.com
graph.facebook.com
以下是我的代码:
我已经拿走了我的主机列表(parent.txt)并对其自身进行了检查,并将所有匹配项吐出到新文件中。
$parent = Get-Content("parent.txt")
$hosts = Get-Content("parent.txt")
$repeats =@()
$out_file = "$PSScriptRoot\repeats.txt"
$hosts | where {
$found = $FALSE
foreach($domains in $parent){
if($_.Contains($domains) -and $_ -ne $domains){
$found = $TRUE
$repeats += $_
}
if($found -eq $TRUE){
break
}
}
$found
}
$repeats = $repeats -join "`n"
[System.IO.File]::WriteAllText($out_file,$repeats)
这似乎是一种非常低效的方法,因为我正在浏览数组的每个元素。关于如何最好地优化这个的任何建议?我有一些想法,比如在检查和检查哪些元素上加入更多条件,但我觉得有一种截然不同的方法会更好。
答案 0 :(得分:2)
首先,严格基于共享域名的解决方案(例如,helpx.adobe.com
和adobe.com
被视为属于同一个域,但list-manage.com
和manage.com
不是)。
这不是你要求的,但对未来的读者可能更有用:
Get-Content parent.txt | Sort-Object -Unique { ($_ -split '\.')[-2,-1] -join '.' }
假设您的示例输入中有list.manage.com
而不是list-manage.com
,上面的命令会产生:
adk2.co
adk2.com
adobe.com
graph.facebook.com
manage.com
{ ($_ -split '\.')[-2,-1] -join '.' }
按最后2个域组件(例如adobe.com
)对输入行进行排序:
-Unique
会丢弃重复项。
共享后缀解决方案,根据要求提供:
# Helper function for (naively) reversing a string.
# Note: Does not work properly with Unicode combining characters
# and surrogate pairs.
function reverse($str) { $a = $str.ToCharArray(); [Array]::Reverse($a); -join $a }
# * Sort the reversed input lines, which effectively groups them by shared suffix
# with the shortest entry first (e.g., the reverse of 'manage.com' before the
# reverse of 'list-manage.com').
# * It is then sufficient to output only the first entry in each group, using
# wildcard matching with -notlike to determine group boundaries.
# * Finally, sort the re-reversed results.
Get-Content parent.txt | ForEach-Object { reverse $_ } | Sort-Object |
ForEach-Object { $prev = $null } {
if ($null -eq $prev -or $_ -notlike "$prev*" ) {
reverse $_
$prev = $_
}
} | Sort-Object
答案 1 :(得分:1)
一种方法是使用哈希表来存储您的所有parent
值,然后对于每个repeat
,将其从表中删除。添加到哈希表时的值1
无关紧要,因为我们只测试密钥是否存在。
$parent = @(
'adk2.co',
'adk2.com',
'adobe.com',
'helpx.adobe.com',
'manage.com',
'list-manage.com'
)
$repeats = (
'adk2.com',
'helpx.adobe.com',
'list-manage.com'
)
$domains = @{}
$parent | % {$domains.Add($_, 1)}
$repeats | % {if ($domains.ContainsKey($_)) {$domains.Remove($_)}}
$domains.Keys | Sort