【问题标题】:Select multiple substrings from a multiline string从多行字符串中选择多个子字符串
【发布时间】:2016-07-12 13:33:25
【问题描述】:

我正在尝试创建一个 PowerShell 脚本来从大型日志文件中挑选特定的行。使用Select-String,我将数据归结为多行字符串中我需要的行。现在我想进一步修改它,只返回这些行中的 ID 号,在一个逗号分隔的字符串中。

当前代码:

if (Select-String $SearchFile -Pattern $SearchString -Quiet) {
    Write-Host "Error message found"
    $body += Select-String $SearchFile -Pattern $SearchString -Context 1,0 |
             foreach {$_.Context.DisplayPreContext} | Out-String
    Send-MailMessage (email_info_here) -Body $body
} else {
    Write-Host "No errors found"
}

当前返回以下字符串:

信息 |为 197988 创建批次 | 2016 年 3 月 24 日凌晨 02:10
信息 |为 202414 创建批次 | 2016 年 3 月 24 日凌晨 02:10
信息 |为 173447 创建批次 | 03/24/2016 02:10 AM

希望输出格式为:

197988, 202414, 173447

【问题讨论】:

  • 目前,在创建 $body 时,您似乎正在推动通过Out-String 找到的所有行。我建议省略 Out-String 部分,它应该将 $body 保留为数组而不是多行字符串。下面的一些答案在数组上​​效果更好(尤其是使用foreach 循环遍历每一行)。

标签: string powershell substring select-string


【解决方案1】:

如果 Body 包含这些行,那么您只需要拆分并索引到包含我们数据的列。

$body | ForEach-Object {$psitem.Split()[5]}
197988
202414
173447  

在这个示例中,我们调用 ForEach-Object 来制作一个小代码块以在每一行上执行。然后,我们调用该行的$split() 方法来分割空格。然后我们只需使用$psitem[5] 索引到第五列。

假设您想再次将这些行保存回 $body,只需将 $body = 添加到第 1 行的前面。

编辑:多行字符串与数组

在原始帖子中,$body 变量是使用Out-String 作为管道中的最后一个命令创建的。这将使其成为单个多行字符串。省略 | Out-String 部分将使 $body 成为字符串数组。后者(一个数组)更容易使用并且是上面的答案所假设的,因为使用foreach 循环遍历数组中的每一行很容易。

两者之间的转换是这样完成的:

$string = @"
INFO | Creating Batch for 197988 | 03/24/2016 02:10 AM
INFO | Creating Batch for 202414 | 03/24/2016 02:10 AM
INFO | Creating Batch for 173447 | 03/24/2016 02:10 AM
"@

$array = @(
"INFO | Creating Batch for 197988 | 03/24/2016 02:10 AM"
"INFO | Creating Batch for 202414 | 03/24/2016 02:10 AM"
"INFO | Creating Batch for 173447 | 03/24/2016 02:10 AM"
)

$array_from_string = $string -split("`n")
$string_from_array = $array | Out-String

为了使答案起作用,您需要确保 $body 是一个数组,否则您只会得到一个 ID 号:

$string | Foreach-Object {$psitem.Split()[5]}
197988

【讨论】:

    【解决方案2】:

    将Out-String 替换为匹配每个结果行的数字部分的Where-Object 过滤器,提取数字子匹配项,然后加入结果:

    $body += (Select-String $SearchFile -Pattern $SearchString -Context 1,0 |
             ForEach-Object { $_.Context.DisplayPreContext } |
             Where-Object { $_ -match 'for (\d+) \|' } |
             ForEach-Object { $matches[1] }) -join ', '
    

    【讨论】:

      【解决方案3】:

      这可能是一种肮脏的方式,但它确实有效:

      #This can also be your variable
      $log = gc "C:\[log path here]"
      
      #Remove beginning of string up to ID
      $log = $log -replace '(.*?)for ' , ""
      
      #Select first 6 characters since all IDs shown are 6 characters
      $logIDs = @()
      foreach($line in $log){
          $logIDs += $line.substring(0,6)
      }
      
      ### At this point $logIDs contains all IDs, now we just need to comma separate them ###
      
      $count = 1
      foreach($ID in $logIDs){
          if($count -eq $logIDs.count){
              $result += $ID
          }
          else{
              $result += $ID+", "
              $count++
          }
      }
      
      #Here are your results separated by commas
      $result
      

      希望这会有所帮助,如果您需要任何类型的变化,请告诉我。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-05-25
        • 2013-05-20
        • 2014-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-10
        • 1970-01-01
        相关资源
        最近更新 更多