需要从主机名转到基域
Need to go from hostname to base domain
我需要一个功能:
f(fqdn,suffix) -> basedomain
使用这些示例输入和输出:
f('foobar.quux.somedomain.com','com') -> 'somedomain.com'
f('somedomain.com','com') -> 'somedomain.com'
f('foobar.quux.somedomain.com.br','com.br') -> 'somedomain.com.br'
f('somedomain.com.br','com.br') -> 'somedomain.com.br'
用简单的英语来说,如果 suffix
有 n
段,取最后的 n+1
段。查找 FQDN 的基域,考虑到某些 FQDN 具有多个后缀元素这一事实。
我需要匹配的后缀是here。我已经在我的 SQL 数据库中找到了它们。
我可以用 C# 写这个;它可能不是最优雅的,但它会起作用。不幸的是,我想在最接近数据的 T-SQL 或 Powershell 中使用此函数,这是使用此数据的其余实用程序所在的位置。我认为可以在 C# 中执行此操作,编译为程序集,然后从 T-SQL 或什至从 Powershell 访问它……如果这将是最快的执行方式。如果在纯 T-SQL 或简单的 Powershell 中有一些相当聪明的替代方案,我会喜欢的。
编辑:我忘记明确提及的一件事(但在查看后缀列表时很清楚,在我上面的 link 中)是我们必须选择 longest 匹配后缀。 "br" 和 "com.br" 都出现在后缀列表中(对于 uk、pt 等,情况类似)。所以 SQL 必须使用 window 函数来确保找到最长的匹配后缀。
这是我在做 SQL 时达到的程度。我迷失了所有 substring
/reverse
函数。
SELECT Domain, suffix
FROM (
SELECT SD.Domain, SL.suffix,
RN=ROW_NUMBER() OVER (
PARTITION BY sd.Domain ORDER BY LEN(SL.suffix) DESC)
FROM SiteDomains SD
INNER JOIN suffixlist SL ON SD.Domain LIKE '%.'+SL.suffix
) AS X
WHERE RN=1
这对于找到正确的后缀很有效。不过,我有点担心它的性能。
以下是我在 C# 中的做法:
string getBaseDomain(string fqdn, string suffix)
{
string[] domainSegs = fqdn.Split('.');
return domainSegs[domainSegs.Length - suffix.Split('.').Length - 1] + "." + suffix;
}
所以它在 Powershell 中:
function getBaseDomain
{
Param(
[string]$fqdn,
[string]$suffix
)
$domainSegs = $fqdn.Split(".");
return $domainSegs[$domainSegs.Length - $suffix.Split(".").Length - 1] + "."+$suffix;
}
在这上面浪费 whosebug.com 的时间现在看来很愚蠢。抱歉。
这是一个 tsql 变体...
declare @fqdn varchar(256) = 'somedomain.com'
declare @suffix varchar(128) = 'com'
select left(@fqdn,CHARINDEX(@suffix,@fqdn) - 2)
if(select CHARINDEX('.',reverse(left(@fqdn,CHARINDEX(@suffix,@fqdn) - 2)))) = 0
begin
select left(@fqdn,CHARINDEX(@suffix,@fqdn) - 2) + '.' + @suffix
end
else
begin
select right(left(@fqdn,CHARINDEX(@suffix,@fqdn) - 2),CHARINDEX('.',reverse(left(@fqdn,CHARINDEX(@suffix,@fqdn) - 2))) - 1) + '.' + @suffix
end
下面演示了将 FQDN 与 TLD 匹配并提取所需的 n + 1 域名段:
-- Sample data.
declare @SampleTLDs as Table ( TLD VarChar(64) );
insert into @SampleTLDs ( TLD ) values
( 'com' ), ( 'somedomain.com' ), ( 'com.br' );
declare @SampleFQDNs as Table ( FQDN VarChar(64) );
insert into @SampleFQDNs ( FQDN ) values
( 'foobar.quux.somedomain.com' ), ( 'somedomain.com' ),
( 'foobar.quux.somedomain.com.br' ), ( 'somedomain.com.br' );
select * from @SampleTLDs;
select * from @SampleFQDNs;
-- Fiddle about.
select FQDN, TLD,
case
when DotPosition = 0 then FQDN
else Reverse( Left( ReversedPrefix, DotPosition - 1) ) + '.' + TLD
end as Result
from (
select FQDNs.FQDN, TLDs.TLD,
Substring( Reverse( FQDNs.FQDN ), Len( TLDs.TLD ) + 2, 100 ) as ReversedPrefix,
CharIndex( '.', Substring( Reverse( FQDNs.FQDN ), Len( TLDs.TLD ) + 2, 100 ) ) as DotPosition
from @SampleFQDNs as FQDNs inner join
@SampleTLDs as TLDs on FQDNs.FQDN like '%.' + TLDs.TLD or FQDNs.FQDN = TLDs.TLD ) as Edna;
-- To select only the longest matching TLD for each FQDN:
with
ExtendedFQDNs as (
select FQDNs.FQDN, TLDs.TLD, Row_Number() over ( partition by FQDN order by Len( TLDs.TLD ) desc ) as TLDLenRank,
Substring( Reverse( FQDNs.FQDN ), Len( TLDs.TLD ) + 2, 100 ) as ReversedPrefix,
CharIndex( '.', Substring( Reverse( FQDNs.FQDN ), Len( TLDs.TLD ) + 2, 100 ) ) as DotPosition
from @SampleFQDNs as FQDNs inner join
@SampleTLDs as TLDs on FQDNs.FQDN like '%.' + TLDs.TLD or FQDNs.FQDN = TLDs.TLD )
select FQDN, TLD,
case
when DotPosition = 0 then FQDN
else Reverse( Left( ReversedPrefix, DotPosition - 1) ) + '.' + TLD
end as Result
from ExtendedFQDNs
where TLDLenRank = 1;
我需要一个功能:
f(fqdn,suffix) -> basedomain
使用这些示例输入和输出:
f('foobar.quux.somedomain.com','com') -> 'somedomain.com'
f('somedomain.com','com') -> 'somedomain.com'
f('foobar.quux.somedomain.com.br','com.br') -> 'somedomain.com.br'
f('somedomain.com.br','com.br') -> 'somedomain.com.br'
用简单的英语来说,如果 suffix
有 n
段,取最后的 n+1
段。查找 FQDN 的基域,考虑到某些 FQDN 具有多个后缀元素这一事实。
我需要匹配的后缀是here。我已经在我的 SQL 数据库中找到了它们。
我可以用 C# 写这个;它可能不是最优雅的,但它会起作用。不幸的是,我想在最接近数据的 T-SQL 或 Powershell 中使用此函数,这是使用此数据的其余实用程序所在的位置。我认为可以在 C# 中执行此操作,编译为程序集,然后从 T-SQL 或什至从 Powershell 访问它……如果这将是最快的执行方式。如果在纯 T-SQL 或简单的 Powershell 中有一些相当聪明的替代方案,我会喜欢的。
编辑:我忘记明确提及的一件事(但在查看后缀列表时很清楚,在我上面的 link 中)是我们必须选择 longest 匹配后缀。 "br" 和 "com.br" 都出现在后缀列表中(对于 uk、pt 等,情况类似)。所以 SQL 必须使用 window 函数来确保找到最长的匹配后缀。
这是我在做 SQL 时达到的程度。我迷失了所有 substring
/reverse
函数。
SELECT Domain, suffix
FROM (
SELECT SD.Domain, SL.suffix,
RN=ROW_NUMBER() OVER (
PARTITION BY sd.Domain ORDER BY LEN(SL.suffix) DESC)
FROM SiteDomains SD
INNER JOIN suffixlist SL ON SD.Domain LIKE '%.'+SL.suffix
) AS X
WHERE RN=1
这对于找到正确的后缀很有效。不过,我有点担心它的性能。
以下是我在 C# 中的做法:
string getBaseDomain(string fqdn, string suffix)
{
string[] domainSegs = fqdn.Split('.');
return domainSegs[domainSegs.Length - suffix.Split('.').Length - 1] + "." + suffix;
}
所以它在 Powershell 中:
function getBaseDomain
{
Param(
[string]$fqdn,
[string]$suffix
)
$domainSegs = $fqdn.Split(".");
return $domainSegs[$domainSegs.Length - $suffix.Split(".").Length - 1] + "."+$suffix;
}
在这上面浪费 whosebug.com 的时间现在看来很愚蠢。抱歉。
这是一个 tsql 变体...
declare @fqdn varchar(256) = 'somedomain.com'
declare @suffix varchar(128) = 'com'
select left(@fqdn,CHARINDEX(@suffix,@fqdn) - 2)
if(select CHARINDEX('.',reverse(left(@fqdn,CHARINDEX(@suffix,@fqdn) - 2)))) = 0
begin
select left(@fqdn,CHARINDEX(@suffix,@fqdn) - 2) + '.' + @suffix
end
else
begin
select right(left(@fqdn,CHARINDEX(@suffix,@fqdn) - 2),CHARINDEX('.',reverse(left(@fqdn,CHARINDEX(@suffix,@fqdn) - 2))) - 1) + '.' + @suffix
end
下面演示了将 FQDN 与 TLD 匹配并提取所需的 n + 1 域名段:
-- Sample data.
declare @SampleTLDs as Table ( TLD VarChar(64) );
insert into @SampleTLDs ( TLD ) values
( 'com' ), ( 'somedomain.com' ), ( 'com.br' );
declare @SampleFQDNs as Table ( FQDN VarChar(64) );
insert into @SampleFQDNs ( FQDN ) values
( 'foobar.quux.somedomain.com' ), ( 'somedomain.com' ),
( 'foobar.quux.somedomain.com.br' ), ( 'somedomain.com.br' );
select * from @SampleTLDs;
select * from @SampleFQDNs;
-- Fiddle about.
select FQDN, TLD,
case
when DotPosition = 0 then FQDN
else Reverse( Left( ReversedPrefix, DotPosition - 1) ) + '.' + TLD
end as Result
from (
select FQDNs.FQDN, TLDs.TLD,
Substring( Reverse( FQDNs.FQDN ), Len( TLDs.TLD ) + 2, 100 ) as ReversedPrefix,
CharIndex( '.', Substring( Reverse( FQDNs.FQDN ), Len( TLDs.TLD ) + 2, 100 ) ) as DotPosition
from @SampleFQDNs as FQDNs inner join
@SampleTLDs as TLDs on FQDNs.FQDN like '%.' + TLDs.TLD or FQDNs.FQDN = TLDs.TLD ) as Edna;
-- To select only the longest matching TLD for each FQDN:
with
ExtendedFQDNs as (
select FQDNs.FQDN, TLDs.TLD, Row_Number() over ( partition by FQDN order by Len( TLDs.TLD ) desc ) as TLDLenRank,
Substring( Reverse( FQDNs.FQDN ), Len( TLDs.TLD ) + 2, 100 ) as ReversedPrefix,
CharIndex( '.', Substring( Reverse( FQDNs.FQDN ), Len( TLDs.TLD ) + 2, 100 ) ) as DotPosition
from @SampleFQDNs as FQDNs inner join
@SampleTLDs as TLDs on FQDNs.FQDN like '%.' + TLDs.TLD or FQDNs.FQDN = TLDs.TLD )
select FQDN, TLD,
case
when DotPosition = 0 then FQDN
else Reverse( Left( ReversedPrefix, DotPosition - 1) ) + '.' + TLD
end as Result
from ExtendedFQDNs
where TLDLenRank = 1;