如何在PowerShell上应用regex?

日期: 2011-03-14 作者:Brandon Shell翻译:Mark 来源:TechTarget中国 英文

是时候讨论一下正则表达式(regex)了。对现代文本解析的惊叹可能说其是IT人士可以拥有的最强大工具之一。简单来说,你可以把正则表达式(也叫regex)当作描述文本的简略方式。例证比描述更为容易,下面我们就来看一个例子。

  假设你有一个复杂的密码规则,要求字母长度至少是8位,并且至少有一个大写或小写字母,至少有一个数字或符号。那么要如何对其进行检查呢?如果你只是手工地来检查每一个密码,而不是用脚本来处理,那这会是一件相当复杂的事情。但如果是使用强大的Windows PowerShell正则表达式,你可以简单地这样来做: $password –match “^.*(?=.{6,})(?=.*[……

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

是时候讨论一下正则表达式(regex)了。对现代文本解析的惊叹可能说其是IT人士可以拥有的最强大工具之一。简单来说,你可以把正则表达式(也叫regex)当作描述文本的简略方式。例证比描述更为容易,下面我们就来看一个例子。

  假设你有一个复杂的密码规则,要求字母长度至少是8位,并且至少有一个大写或小写字母,至少有一个数字或符号。那么要如何对其进行检查呢?如果你只是手工地来检查每一个密码,而不是用脚本来处理,那这会是一件相当复杂的事情。但如果是使用强大的Windows PowerShell正则表达式,你可以简单地这样来做:

$password –match “^.*(?=.{6,})(?=.*[a-z])(?=.*[A-Z])(?=.*[dW]).*$”

  我知道现在这看起来令人却步,但是相信我,我很理解这一点。在我IT生涯中的大部分时间中,我也害怕使用正则表达式。它们总是显得那么神秘和复杂,以至于我认为我会永远学不会。但在我使用PowerShell不久之后,我有了要简单使用正则表达式的需要,所以我只能咬紧牙关。但是令我惊讶的是,它没有我想象中的那么难。但不要误会我的意思,它们可能变得非常复杂,而且我认为我的“regex foo”最多只能算业余。

  因此,虽然正则表达式教学超出了本文的范围,但理解与期相关的其余一般知识非常重要。假如你对正则表达式不熟悉,你可以从基础开始学习。这将不会花费你很多时间,并且它是十分值得的。

  最后,在我们进入PowerShell的regex世界之前要记住,正则表达式有多种“口味””,并且大多数都是我们非常熟悉的,不过它们确实有些轻微的差别。在这种情况下,我们将使用.NET Framework 4来处理。

  Windows PowerShell的正则表达式工具

  下面我们来看一下一些regex命令和如何使用它们的例子。

  Match operator–它使用正则表达式来匹配一个字符串。

  示例:

$password–match “^.*(?=.{6,})(?=.*[a-z])(?=.*[A-Z])(?=.*[dW]).*$”

  $matches–它是由Switch、-match或-notmatch操作员创建的,包含了所有匹配字符串值的哈希表。

  System.Text.RegularExpressions.Regex–这是一个用来处理正则表达式的.NET类。PowerShell有一个针对该[RegEx]的内置捷径,所以你可以使用下面的简单操作来创建一个实例。

$ComplexPasswordRegEx = [RegEx] “^.*(?=.{6,})(?=.*[a-z])(?=.*[A-Z])(?=.*[dW]).*$”

  Switch–这是在PowerShell语言中最强大的一个循环结构(并且可能值得写一篇专门的相关文章),但是现在我们只打算谈谈- regex标志。你可以使用带–regex标志的Switch来在字符串数组中移动,并且在每个“匹配值”上执行scriptblock。

  示例:

Switch –regex ($MyPasswords)
{
“^.*(?=.{6,})(?=.*[a-z])(?=.*[A-Z])(?=.*[dW]).*$” {“Valid Password”}
Default {“Invalid Password”}
}

  在Switch上使用help about_switch命令,来得到更多的信息。

  整合regex命令

  最后,下面是我写的一个PowerShell函数,它运用了所有上述工具来解析netstat命令的结果且创建了一个更易于“传递”的PowerShell对象。

function Get-NetStat
{
  [Cmdletbinding(DefaultParameterSetName="All")]
  Param(
    [Parameter()]
    [string]$ProcessName,
    [Parameter()]
    [ValidateSet("LISTENING",
    "ESTABLISHED", "CLOSE_WAIT","TIME_WAIT")]
    [string]$State,
    [Parameter(ParameterSetName="Interval")]
    [int]$Interval,
    [Parameter()]
    [int]$Sleep = 1,
    [Parameter(ParameterSetName="Loop")]
    [switch]$Loop
  )
  function Parse-Netstat ($NetStat)
  {
    Write-Verbose " [Parse-Netstat] :: Parsing Netstat
    results"
    switch -regex ($NetStat)
    {
      $RegEx
      {
        Write-Verbose " [Parse-Netstat] :: creating
              Custom object"
        $myobj = @{
          Protocol      = $matches.Protocol
          LocalAddress  = $matches.LocalAddress.split(":")[0]
          LocalPort     = $matches.LocalAddress.split(":")[1]
          RemoteAddress = $matches.RemoteAddress.split(":")[0]
          RemotePort    = $matches.RemoteAddress.split(":")[1]
          State         = $matches.State
          ProcessID     = $matches.PID
          ProcessName   = Get-Process-id $matches.PID -ea 0 |
                          %{$_.name}
            }
        $obj = New-Object PSCustomObject -Property $myobj
        $obj.PSTypeNames.Clear()
        $obj.PSTypeNames.Add('BSonPosh.NetStatInfo')
        Write-Verbose " [Parse-Netstat] :: Created object for
        [$($obj.LocalAddress):$($obj.LocalPort)]"
        if($ProcessName)
        {
          $obj | where{$_.ProcessName -eq $ProcessName}
        }
        elseif($State)
        {
          $obj | where{$_.State -eq $State}
        }
        else
        {
          $obj
        }
          }
    }
 }
  [RegEX]$RegEx =
's+(?<Protocol>S+)s+(?<LocalAddress>S+)s+(?<RemoteAddress>S+)s+(?< 0;State>S+) s+(?<PID>S+)'
  $Connections = @{}
  switch -exact ($pscmdlet.ParameterSetName)
  {
    "All"   {
            Write-Verbose " [Get-NetStat] ::
            ParameterSet - ALL"
            $NetStatResults = netstat -ano |
            ?{ $_ -match "(TCP|UDP)s+d"}
            Parse-Netstat $NetStatResults
          }
    "Interval"     {
            Write-Verbose" [Get-NetStat] :: ParameterSet -
            Interval"
            for($i = 1 ; $i -le $Interval ; $i++)
            {
            Start-Sleep$Sleep
            $NetStatResults= netstat -ano |
            ?{ $_ -match "(TCP|UDP)s+d"}
            Parse-Netstat$NetStatResults | Out-String
          }
        }
    "Loop"        {
        Write-Verbose" [Get-NetStat] :: ParameterSet - Loop"
        Write-Host
        Write-Host "Protocol LocalAddress LocalPort
        RemoteAddress RemotePort State
        ProcessName
PID"
        Write-Host"-------- ------------ --------- ----------
        ---------- ----- ----------- ---"
        -ForegroundColor
White
               $oldPos = $Host.UI.RawUI.CursorPosition
        [console]::TreatControlCAsInput = $true
        while($true)
        {
          Write-Verbose" [Get-NetStat] :: Getting Netstat
          data"
          $NetStatResults = netstat -ano |
          ?{ $_ -match "(TCP|UDP)s+d"}
          Write-Verbose" [Get-NetStat] :: Getting Netstat
                         data from Netstat"
          $Results = Parse-Netstat $NetStatResults
          Write-Verbose" [Get-NetStat] :: Parse-NetStat
          returned $($results.count) results"
          foreach($Result in $Results)
          {
            $Key = $Result.LocalPort
            $Value = $Result.ProcessID
            $msg = "{0,-9}{1,-14}{2,-10}{3,-15}{4,-11}{5,-12}
                    {6,-14}{7,-10}" –f
$Result.Protocol, $Result.LocalAddress, $Result.LocalPort,
$Result.RemoteAddress, $Result.RemotePort, $Result.State,
                        $Result.ProcessName, $Result.ProcessID
            if($Connections.$Key -eq $Value)
            {
              Write-Host$msg
            }
            else
            {
              $Connections.$Key = $Value
              Write-Host$msg -ForegroundColor Yellow
            }
          }
          if($Host.UI.RawUI.KeyAvailable -and (3 -eq
[int]$Host.UI.RawUI.ReadKey("AllowCtrlC,
IncludeKeyUp,NoEcho").Character))
          {
            Write-Host"Exiting now..." -foregroundcolor Yellow
            Write-Host
            [console]::TreatControlCAsInput = $false
            break
          }
          $Host.UI.RawUI.CursorPosition = $oldPos
          start-sleep$Sleep
        }
      }
}
}

相关推荐