【问题标题】:Regular Expressions in powershell splitpowershell拆分中的正则表达式
【发布时间】:2019-04-29 16:40:39
【问题描述】:

我需要根据输入将 UNC fqdn 名称删除为名称或 IP。

我的例子是

\\tom.overflow.corp.com
\\123.43.234.23.overflow.corp.com

我只想得到tom123.43.234.23

我的数组中有以下代码可以完美地删除域名,但我仍然留下\\tom

-Split '\.(?!\d)')[0]

【问题讨论】:

  • 你试过regex101.com吗?
  • @Kory Gill 谢谢你,不错的网站,我会更多地使用它。仍然没有找到我的解决方案。

标签: regex powershell powershell-2.0 powershell-3.0 regex-lookarounds


【解决方案1】:

虽然这不是正则表达式,但它确实有效。 [grin] 我怀疑如果您有大量此类项目,那么您将需要一个正则表达式。它们确实比简单的文本运算符要快。

这将摆脱领先的\\,然后将域名替换为 .

# fake reading in a text file
#    in real life, use Get-Content
$InStuff = -split @'
\\tom.overflow.corp.com
\\123.43.234.23.overflow.corp.com
'@

$DomainName = '.overflow.corp.com'

$InStuff.ForEach({
    $_.TrimStart('\\').Replace($DomainName, '')
    })

输出...

tom
123.43.234.23

【讨论】:

  • 谢谢。不是我真正想要的,我不想添加更多代码。 '\.(?!\d)' 不是正则表达式吗?用那一点点代码,我几乎可以完成我想做的事情。我会继续努力
  • @jimwood - 从我所见,这似乎不像是“添加更多代码”。 [grin] LotPings 发布的代码比我发布的要长得多。另外,我的代码很容易理解——正则表达式并不那么明显。 ///// 但是,如果您需要 SPEED,那么正则表达式方法可能是可行的方法。
  • 我的代码将删除 any 尾随域部分,而您的代码固定为给定的部分,因此功能不计长度。吹毛求疵:我的是 75 个字符/你的是 ~100
  • @LotPings - 这并不是对您的代码的任何批评。如果看起来是这样,我很抱歉。 [blush] 这是对 OP 拒绝我的理由的批评。 [grin] 正如我所提到的,对于大型数据集,正则表达式几乎肯定会更快 - 如果 OP 有这样的需求。 ///// 我假设 OP 只提供了一个域,而不是“哎呀!我应该提到会改变”。 /////顺便说一句,你的正则表达式会处理Tom.Dooley.Overflow.Corp.com吗?这就是我放弃正则表达式的原因......我想不出任何方法来处理可能的域前部分。 [脸红]
【解决方案2】:

我在偷Lee_Daileys $InSTuff 但附加一个RegEx I used recently

$InStuff = -split @'
\\tom.overflow.corp.com
\\123.43.234.23.overflow.corp.com
'@
$InStuff |ForEach-Object {($_.Trim('\\') -split '\.(?!\d{1,3}(\.|$))')[0]}

样本输出:

tom
123.43.234.23

正如您在RegEx101 上看到的,数字之间的点匹配

【讨论】:

    【解决方案3】:

    您的正则表达式原则上成功拆分了感兴趣的标记,但它没有考虑输入字符串中的前导 \\

    您可以使用正则表达式替换 (|) 在开头包含前导 \\ 作为附加的-split 分隔符

    鉴于匹配输入开头的分隔符会创建一个索引为0 元素,因此您需要访问索引1 以获取感兴趣的子字符串。

    简而言之:传递给-split 的正则表达式应该是'^\\\\|\.(?!\d)' 而不是'\.(?!\d)',用于访问结果数组的索引应该是[1] 而不是[0]

    '\\tom.overflow.corp.com', '\\123.43.234.23.overflow.corp.com' | 
      ForEach-Object { ($_ -Split '^\\\\|\.(?!\d)')[1] }
    

    以上产出:

    tom
    123.43.234.23
    

    或者,您可以在单独的步骤中删除前导\\,使用-replace

    '\\tom.overflow.corp.com', '\\123.43.234.23.overflow.corp.com' | 
      ForEach-Object { ($_ -Split '\.(?!\d)')[0] -replace '^\\\\' }
    

    然而另一种选择是使用单个-replace操作,它不需要ForEach-Object调用(不需要需要显式迭代):

    '\\tom.overflow.corp.com', '\\123.43.234.23.overflow.corp.com' -replace
      '?(x) ^\\\\ (.+?) \.\D .+', '$1'
    
    • 内联选项(?x) (IgnoreWhiteSpace) 允许您使用无关紧要的空格使正则表达式更具可读性:任何未转义的空格都可用于视觉格式化。

      李>
    • ^\\\\ 匹配每个字符串开头 (^) 处的 \\(用 \ 转义)。

    • (.+?) 惰性匹配一个或多个字符。

    • \.\D 匹配文字 . 后跟 other 而非数字(\d 匹配数字,\D 是它的否定)。

    • .+ 匹配一个或多个剩余字符,即输入的其余部分。

    • $1 作为替换操作数是指正则表达式中的第一个捕获组 ((...)) 匹配的内容,并且鉴于正则表达式旨在使用整个字符串,因此仅将其替换为那个。

    【讨论】:

    • 很高兴听到这个消息,@jimwood;我的荣幸。顺便说一句:虽然由于是此答案的作者,我个人收到了您的评论,但在此回答的其他人却没有。
    【解决方案4】:

    Select-String 函数使用正则表达式并使用匹配项填充 MatchInfo 对象(然后可以对其进行查询)。

    正则表达式 "(\.?\d+)+|\w+" 适用于您的特定示例。

    "\\tom.overflow.corp.com", "\\123.43.234.23.overflow.corp.com" |
      Select-String "(\.?\d+)+|\w+" | % { $_.Matches.Value }
    

    【讨论】:

      猜你喜欢
      • 2013-11-19
      • 2019-01-30
      • 2021-10-07
      • 1970-01-01
      • 2012-11-05
      • 2013-08-11
      • 2021-12-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多