Tsql 需要从主机名转到基本域
我需要一个函数:Tsql 需要从主机名转到基本域,tsql,powershell,fqdn,Tsql,Powershell,Fqdn,我需要一个函数: 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.c
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'
在普通英语中,如果后缀
有n
段,则取最后的n+1
段。查找FQDN的基域,允许某些FQDN具有多个后缀元素
我需要匹配的后缀是。我已经在我的SQL数据库中找到了它们
我可以用C写这个;它可能不是最优雅的,但它会起作用。不幸的是,我希望在T-SQL中使用此函数,因为它最接近数据,或者在Powershell中使用此函数,而使用此数据的其他实用程序将在Powershell中使用此函数。我想可以在C#中完成,编译成一个程序集,然后从T-SQL甚至Powershell访问它。。。如果这是执行速度最快的。如果在纯T-SQL或简单Powershell中有一些相当聪明的替代方案,我很乐意
编辑:有一件事我忘了明确提到(但在我上面的链接中查看后缀列表时很清楚),那就是我们必须选择最长的匹配后缀。“br”和“com.br”都出现在后缀列表中(类似的事情发生在uk、pt等)。因此,SQL必须使用窗口函数来确保找到最长的匹配后缀
下面是我在执行SQL时取得的成绩。我在所有的子字符串
/反向
函数中迷失了方向
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#中的做法: 因此,它位于Powershell中:
function getBaseDomain
{
Param(
[string]$fqdn,
[string]$suffix
)
$domainSegs = $fqdn.Split(".");
return $domainSegs[$domainSegs.Length - $suffix.Split(".").Length - 1] + "."+$suffix;
}
现在看来,浪费stackoverflow.com的时间来做这件事是相当愚蠢的。我的道歉。以下是我在C#中的做法: 因此,它位于Powershell中:
function getBaseDomain
{
Param(
[string]$fqdn,
[string]$suffix
)
$domainSegs = $fqdn.Split(".");
return $domainSegs[$domainSegs.Length - $suffix.Split(".").Length - 1] + "."+$suffix;
}
现在看来,浪费stackoverflow.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
这是一个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;
下面演示如何将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;
我想您应该在C#中使用.NET字符串操作来完成任务,对吗?如果是这样,您可以在powershell中执行完全相同的操作(字符串处理是相同的,C中可用的所有方法也可以在powershell中使用)
$fqdn-替换“*?(?=[^.]+\.$suffix)”
@TessellatingHeckler-wow。这是一个非常简单的正则表达式解决方案。不幸的是,它不能证明像foo.bar.com.br.something.com.br这样的东西,甚至像my.computers.com这样的东西。除了依赖正则表达式和字符串操作之外,我认为还有更好的方法。这应该可以很容易地转换为PowerShell,并且[system.uri]
也与此相关:我假设您将在C#中使用.NET字符串操作来完成任务,对吗?如果是这样,您可以在powershell中执行完全相同的操作(字符串处理是相同的,C中可用的所有方法也可以在powershell中使用)$fqdn-替换“*?(?=[^.]+\.$suffix)”
@TessellatingHeckler-wow。这是一个非常简单的正则表达式解决方案。不幸的是,它不能证明像foo.bar.com.br.something.com.br这样的东西,甚至像my.computers.com这样的东西。除了依赖正则表达式和字符串操作之外,我认为还有更好的方法。这应该可以很容易地转化为PowerShell,并且与[system.uri]
也相关:看看答案和注释,你不需要为此道歉:)看看答案和注释,你不需要为此道歉:)这很好,但需要改进,我在问题中没有明确提到(但如果您查看后缀列表链接,它是隐式的。)“br”和“com.br”出现在后缀列表中;最长的后缀必须是首选后缀。我将把它添加到我的问题中。这与查找最长匹配后缀的技术相结合时效果非常好。如果你更新了答案,我将接受它。@RossPresser答案已更新:(1)更正了样本日期,(b)更正了FQDN=TLD案例的处理,(iii)添加了为每个FQDN选择“最佳”(即最长TLD)匹配的示例。这很好,但需要改进,我在问题中没有明确提到(但如果查看后缀列表链接,这是隐式的)。“br”和“com.br”出现在后缀列表中;最长的后缀必须是首选后缀。我将把它添加到我的问题中。这与查找最长匹配后缀的技术相结合时效果非常好。如果你更新了答案,我将接受它。@RossPresser答案已更新:(1)更正了样本日期,(b)更正了FQDN=TLD情况的处理,(iii)添加了为每个FQDN选择“最佳”(即最长TLD)匹配的示例。