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)匹配的示例。