在 Powershell 中从 String 中提取字符串

Extracting strings from String in Powershell

我有一个字符串long string: its a teamcity buildLog 这是来自 teamcity 的 buildLog。

[11:27:30] :     [Step 5/5] 15:27:30 INFO: Average times: total 0.455, latency 0.455, connect 0.004
[11:27:30] :     [Step 5/5] 15:27:30 INFO: Percentiles:
[11:27:30] :     [Step 5/5] +---------------+---------------+
[11:27:30] :     [Step 5/5] | Percentile, % | Resp. Time, s |
[11:27:30] :     [Step 5/5] +---------------+---------------+
[11:27:30] :     [Step 5/5] |           0.0 |         0.021 |
[11:27:30] :     [Step 5/5] |          50.0 |         0.103 |
[11:27:30] :     [Step 5/5] |          90.0 |         1.166 |
[11:27:30] :     [Step 5/5] |          95.0 |          2.27 |
[11:27:30] :     [Step 5/5] |          99.0 |          2.77 |
[11:27:30] :     [Step 5/5] |          99.9 |         6.996 |
[11:27:30] :     [Step 5/5] |         100.0 |        10.312 |
[11:27:30] :     [Step 5/5] +---------------+---------------+
[11:27:30] :     [Step 5/5] 15:27:30 INFO: Request label stats:
[11:27:30] :     [Step 5/5] +------------------------------------------+--------+---------+--------+-------------+
[11:27:30] :     [Step 5/5] | label                                    | status |    succ | avg_rt | error       |
[11:27:30] :     [Step 5/5] +------------------------------------------+--------+---------+--------+-------------+
[11:27:30] :     [Step 5/5] | Activity History                         |   OK   | 100.00% |  1.608 |             |
[11:27:30] :     [Step 5/5] | Asset Allocation                         |   OK   | 100.00% |  0.100 |             |
[11:27:30] :     [Step 5/5] | Dashboard Cards and Employee Information |   OK   | 100.00% |  0.255 |             |
[11:27:30] :     [Step 5/5] | Fund Details                             |   OK   | 100.00% |  0.825 |             |
[11:27:30] :     [Step 5/5] | Investments                              |   OK   | 100.00% |  0.132 |             |
[11:27:30] :     [Step 5/5] | Minimum Version                          |   OK   | 100.00% |  0.032 |             |
[11:27:30] :     [Step 5/5] | Rate of Return                           |   OK   | 100.00% |  0.047 |             |
[11:27:30] :     [Step 5/5] | Retirement Outlook Card                  |   OK   | 100.00% |  1.166 |             |
[11:27:30] :     [Step 5/5] | Retirement Outlook Full                  |   OK   | 100.00% |  1.160 |             |
[11:27:30] :     [Step 5/5] | Savings Rate                             |   OK   | 100.00% |  0.112 |             |
[11:27:30] :     [Step 5/5] | Secure Auth Login                        |  FAIL  |  98.58% |  0.207 | Bad Request |
[11:27:30] :     [Step 5/5] | Validate Savings Rate Change             |   OK   | 100.00% |  0.127 |             |
[11:27:30] :     [Step 5/5] | Vested Balance                           |   OK   | 100.00% |  0.157 |             |
[11:27:30] :     [Step 5/5] +------------------------------------------+--------+---------+--------+-------------+
[11:27:35] :     [Step 5/5] 15:27:35 INFO: Ending data feeding...
[11:27:36] :     [Step 5/5] 15:27:36 INFO: Online report link: https://a.blazemeter.com/app/#/masters/36669958

从上面的构建日志中,我必须获取 Percentiles TableRequest Label Stats table 和 Online Report Link

我试过下面的代码,但它正在返回 none:

$firststring = "Percentiles:"
$secondstring = "Request label stats:"
$pattern =  "$firststring(.*?)$secondstring"
$result = [regex]::Match($file,$pattern).Groups[1].Value
$result >> returns none

及以下获取字符串的代码。

$Regex = [Regex]::new("(?<=Percentiles:)(.*)(?=Request label stats:)")
$Match = $Regex.Match($status)
if($Match.Success)
{
  $Match.Value
}

这也是returnsnone。 任何帮助将不胜感激。

我无法为您检查 PowerShell 3.0。但以下内容适用于 Windows PowerShell 5.1。我有两个解决方案,一个包含第一条信息行作为匹配的一部分,另一个不包含。

# Set up your strings to look for
$firststring = [regex]::Escape("Percentiles:")
$secondstring = [regex]::Escape("Request label stats:")

# Pattern which includes the line with $firststring
$withInfoPattern = ".*$firststring(.*\n)*(?=.*$secondstring)"

# Pattern which omits the line with $firststring
$withoutInfoPattern = "(?<=$firststring\s+)(.*\n)*(?=.*$secondstring)"

# We will use $withInfoPattern in this example but you could also use $withoutInfoPattern
# This assumes your content string is in a variable called $content
$matchedContent = if( $content -match $withInfoPattern ) {
  $matches[0]
}

This shows how to match on your first case, the Percentiles table data. To grab the second table and report link you should be able to use the code above and explanations below to extract this data as well as a learning exercise.

此时 $matchedContent 将包含您要查找的输出。如果您不希望匹配的第一行被 return 编辑,您也可以使用 $withoutInfoPattern 进行匹配。我将在下面解释:

  • 虽然在这种情况下不需要,但最好将要通过 [regex]::Escape(string) 插入到正则表达式模式中的字符串放入其中。这是一个很好的做法,可以防止您将来无意中忘记使用特殊正则表达式字符对字符串进行转义。
  • $withInfoPattern 匹配 $firststring 前面有或没有字符的任何行。 $withoutInfoPattern 而是使用正向后视来确保匹配的内容继续出现 $firstString.
  • (.*\n)* 使用捕获组来匹配任何字符或不匹配字符(这就是 .* 的意思),然后是换行符。默认情况下,换行符不与 . 匹配,并且无法使用 -match 运算符更改此行为。尾随 * 查找前面捕获组的任何实例或不查找任何实例。
    • -match 通常不会跨换行匹配。以这种方式使用 (.*\n)* 可以绕过该限制。
  • (?=.*$secondString) 是一个积极的前瞻,以确保模式主模式先于前瞻中指定的模式。 .*$secondString 将从行首开始匹配,因此我们正在查找该行上任何后跟 $secondString 的字符。
  • 调用 -match 运算符在 $content 中查找 $withInfoPattern(或 $withoutInfoPattern)。这假设您正在搜索的字符串作为字符串存储在一个名为 $content 的变量中(而不是字符串数组,因为 Get-Content 默认情况下会这样做。
    • 您可以使用 $content = Get-Content -Raw 将文件作为带有换行符的单个字符串读取,或者在匹配之前使用换行符加入 $content 数组:$content -join "`n"
  • -match 将 return $true$false。如果$true,则可以从第一个索引中的自动变量$matches中获取匹配的内容。由于数组使用从零开始的索引,因此转换为 $matches[0].

其他正则表达式提示

我强烈建议使用站点 https://regexr.com/ 来测试您的表达式。虽然它只支持 JavaScript 和 PCRE 引擎,但两者都足够接近 .NET regex 引擎,而它通常不支持一个问题。即使您发现某些表达式不起作用,它也能很好地解释不同的正则表达式标记,并且在您开发表达式时,它会在底部窗格中解释每个字符序列的含义。

一旦你掌握了正则表达式模式,你就可以使用 switch 到 运行 通过日志行并从你的表中构建对象。下面我将其分解为单独的函数。

$log = @'
[11:27:30] :     [Step 5/5] 15:27:30 INFO: Average times: total 0.455, latency 0.455, connect 0.004
[11:27:30] :     [Step 5/5] 15:27:30 INFO: Percentiles:
[11:27:30] :     [Step 5/5] +---------------+---------------+
[11:27:30] :     [Step 5/5] | Percentile, % | Resp. Time, s |
[11:27:30] :     [Step 5/5] +---------------+---------------+
[11:27:30] :     [Step 5/5] |           0.0 |         0.021 |
[11:27:30] :     [Step 5/5] |          50.0 |         0.103 |
[11:27:30] :     [Step 5/5] |          90.0 |         1.166 |
[11:27:30] :     [Step 5/5] |          95.0 |          2.27 |
[11:27:30] :     [Step 5/5] |          99.0 |          2.77 |
[11:27:30] :     [Step 5/5] |          99.9 |         6.996 |
[11:27:30] :     [Step 5/5] |         100.0 |        10.312 |
[11:27:30] :     [Step 5/5] +---------------+---------------+
[11:27:30] :     [Step 5/5] 15:27:30 INFO: Request label stats:
[11:27:30] :     [Step 5/5] +------------------------------------------+--------+---------+--------+-------------+
[11:27:30] :     [Step 5/5] | label                                    | status |    succ | avg_rt | error       |
[11:27:30] :     [Step 5/5] +------------------------------------------+--------+---------+--------+-------------+
[11:27:30] :     [Step 5/5] | Activity History                         |   OK   | 100.00% |  1.608 |             |
[11:27:30] :     [Step 5/5] | Asset Allocation                         |   OK   | 100.00% |  0.100 |             |
[11:27:30] :     [Step 5/5] | Dashboard Cards and Employee Information |   OK   | 100.00% |  0.255 |             |
[11:27:30] :     [Step 5/5] | Fund Details                             |   OK   | 100.00% |  0.825 |             |
[11:27:30] :     [Step 5/5] | Investments                              |   OK   | 100.00% |  0.132 |             |
[11:27:30] :     [Step 5/5] | Minimum Version                          |   OK   | 100.00% |  0.032 |             |
[11:27:30] :     [Step 5/5] | Rate of Return                           |   OK   | 100.00% |  0.047 |             |
[11:27:30] :     [Step 5/5] | Retirement Outlook Card                  |   OK   | 100.00% |  1.166 |             |
[11:27:30] :     [Step 5/5] | Retirement Outlook Full                  |   OK   | 100.00% |  1.160 |             |
[11:27:30] :     [Step 5/5] | Savings Rate                             |   OK   | 100.00% |  0.112 |             |
[11:27:30] :     [Step 5/5] | Secure Auth Login                        |  FAIL  |  98.58% |  0.207 | Bad Request |
[11:27:30] :     [Step 5/5] | Validate Savings Rate Change             |   OK   | 100.00% |  0.127 |             |
[11:27:30] :     [Step 5/5] | Vested Balance                           |   OK   | 100.00% |  0.157 |             |
[11:27:30] :     [Step 5/5] +------------------------------------------+--------+---------+--------+-------------+
[11:27:35] :     [Step 5/5] 15:27:35 INFO: Ending data feeding...
[11:27:36] :     [Step 5/5] 15:27:36 INFO: Online report link: https://a.blazemeter.com/app/#/masters/36669958
'@ -split '\r?\n'

function get-percentiles {
    param()
    $headerPattern = '\| Percentile'
    $endPattern = '^[^|+]*$'
    $inTable = $false
    switch -regex ($log) {
        $headerPattern {
            $inTable = $true
            continue
        }
        $endPattern {
            if ($inTable) { break } else { continue }
        }
        '\|([^|]+)\|([^|]+).*$' {
            if ($inTable) {
                [PSCustomObject]@{
                    Percentile = $Matches[1].Trim()
                    Time       = $Matches[2].Trim()
                }
            }
        }
    }
}

function get-labeltable {
    param()
    $headerPattern = '\| label'
    $endPattern = '^[^|+]*$'
    $inTable = $false
    switch -regex ($log) {
        $headerPattern {
            $inTable = $true
            continue
        }
        $endPattern {
            if ($inTable) { break } else { continue }
        }
        '\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+).*$' {
            if ($inTable) {
                [PSCustomObject]@{
                    Label  = $Matches[1].Trim()
                    Status = $Matches[2].Trim()
                    Succ   = $Matches[3].Trim()
                    AvgRT  = $Matches[4].Trim()
                    Error  = $Matches[5].Trim()
                }
            }
        }
    }
}

get-percentiles | Format-Table
get-labeltable | Format-Table

输出

Percentile Time
---------- ----
0.0        0.021
50.0       0.103
90.0       1.166
95.0       2.27
99.0       2.77
99.9       6.996
100.0      10.312


Label                                    Status Succ    AvgRT Error
-----                                    ------ ----    ----- -----
Activity History                         OK     100.00% 1.608
Asset Allocation                         OK     100.00% 0.100
Dashboard Cards and Employee Information OK     100.00% 0.255
Fund Details                             OK     100.00% 0.825
Investments                              OK     100.00% 0.132
Minimum Version                          OK     100.00% 0.032
Rate of Return                           OK     100.00% 0.047
Retirement Outlook Card                  OK     100.00% 1.166
Retirement Outlook Full                  OK     100.00% 1.160
Savings Rate                             OK     100.00% 0.112 
Secure Auth Login                        FAIL   98.58%  0.207 Bad Request
Validate Savings Rate Change             OK     100.00% 0.127
Vested Balance                           OK     100.00% 0.157

我知道这个问题已经得到解答,但这是我的两分钱:

$log = @"
[11:27:30] :     [Step 5/5] 15:27:30 INFO: Average times: total 0.455, latency 0.455, connect 0.004
[11:27:30] :     [Step 5/5] 15:27:30 INFO: Percentiles:
[11:27:30] :     [Step 5/5] +---------------+---------------+
[11:27:30] :     [Step 5/5] | Percentile, % | Resp. Time, s |
[11:27:30] :     [Step 5/5] +---------------+---------------+
[11:27:30] :     [Step 5/5] |           0.0 |         0.021 |
[11:27:30] :     [Step 5/5] |          50.0 |         0.103 |
[11:27:30] :     [Step 5/5] |          90.0 |         1.166 |
[11:27:30] :     [Step 5/5] |          95.0 |          2.27 |
[11:27:30] :     [Step 5/5] |          99.0 |          2.77 |
[11:27:30] :     [Step 5/5] |          99.9 |         6.996 |
[11:27:30] :     [Step 5/5] |         100.0 |        10.312 |
[11:27:30] :     [Step 5/5] +---------------+---------------+
[11:27:30] :     [Step 5/5] 15:27:30 INFO: Request label stats:
[11:27:30] :     [Step 5/5] +------------------------------------------+--------+---------+--------+-------------+
[11:27:30] :     [Step 5/5] | label                                    | status |    succ | avg_rt | error       |
[11:27:30] :     [Step 5/5] +------------------------------------------+--------+---------+--------+-------------+
[11:27:30] :     [Step 5/5] | Activity History                         |   OK   | 100.00% |  1.608 |             |
[11:27:30] :     [Step 5/5] | Asset Allocation                         |   OK   | 100.00% |  0.100 |             |
[11:27:30] :     [Step 5/5] | Dashboard Cards and Employee Information |   OK   | 100.00% |  0.255 |             |
[11:27:30] :     [Step 5/5] | Fund Details                             |   OK   | 100.00% |  0.825 |             |
[11:27:30] :     [Step 5/5] | Investments                              |   OK   | 100.00% |  0.132 |             |
[11:27:30] :     [Step 5/5] | Minimum Version                          |   OK   | 100.00% |  0.032 |             |
[11:27:30] :     [Step 5/5] | Rate of Return                           |   OK   | 100.00% |  0.047 |             |
[11:27:30] :     [Step 5/5] | Retirement Outlook Card                  |   OK   | 100.00% |  1.166 |             |
[11:27:30] :     [Step 5/5] | Retirement Outlook Full                  |   OK   | 100.00% |  1.160 |             |
[11:27:30] :     [Step 5/5] | Savings Rate                             |   OK   | 100.00% |  0.112 |             |
[11:27:30] :     [Step 5/5] | Secure Auth Login                        |  FAIL  |  98.58% |  0.207 | Bad Request |
[11:27:30] :     [Step 5/5] | Validate Savings Rate Change             |   OK   | 100.00% |  0.127 |             |
[11:27:30] :     [Step 5/5] | Vested Balance                           |   OK   | 100.00% |  0.157 |             |
[11:27:30] :     [Step 5/5] +------------------------------------------+--------+---------+--------+-------------+
[11:27:35] :     [Step 5/5] 15:27:35 INFO: Ending data feeding...
[11:27:36] :     [Step 5/5] 15:27:36 INFO: Online report link: https://a.blazemeter.com/app/#/masters/36669958

"@

# first parse out the link
$link = ([regex]'(?m)Online report link:\s(.*)$').Match($log).Groups[1].Value

# next remove all except the tables themselves and split into separate lines
$log = $log -replace '(?m)^[^|+]+' -split '\r?\n'

# create two List objects to capture the tables as PsObjects
$percentList = [System.Collections.Generic.List[object]]::new()
$requestList = [System.Collections.Generic.List[object]]::new()

# use switch to loop over the lines
$percentTable = $requestTable = $false
switch -Regex ($log) {
    '^\|\s(Percentile|label)'  { 
        $percentTable = ($matches[1] -eq 'Percentile')
        $requestTable = !$percentTable
        $headers = ($_.Trim("|") -split '\|').Trim()
        continue
    }
    '^\|.*\|$' {
        $tempHash = [ordered]@{}
        $values = ($_.Trim("|") -split '\|').Trim()
        for ($i = 0; $i -lt $headers.Count; $i++) {
            # if you want the numeric values as [double] instead of [string] in the resulting objects, use:
            # $tempHash[$headers[$i]] = if ($values[$i] -as [double]) {[double]$values[$i]} else {$values[$i]}
            $tempHash[$headers[$i]] = $values[$i]
        }
        if ($percentTable) { 
            $percentList.Add([PscustomObject]$tempHash) 
        } 
        else { 
            $requestList.Add([PscustomObject]$tempHash)
        }
    }
}

# show what we have on screen
$percentList | Format-Table -AutoSize
$requestList | Format-Table -AutoSize
$link

输出:

Percentile, % Resp. Time, s
------------- -------------
0.0           0.021        
50.0          0.103        
90.0          1.166        
95.0          2.27         
99.0          2.77         
99.9          6.996        
100.0         10.312       



label                                    status succ    avg_rt error      
-----                                    ------ ----    ------ -----      
Activity History                         OK     100.00% 1.608             
Asset Allocation                         OK     100.00% 0.100             
Dashboard Cards and Employee Information OK     100.00% 0.255             
Fund Details                             OK     100.00% 0.825             
Investments                              OK     100.00% 0.132             
Minimum Version                          OK     100.00% 0.032             
Rate of Return                           OK     100.00% 0.047             
Retirement Outlook Card                  OK     100.00% 1.166             
Retirement Outlook Full                  OK     100.00% 1.160             
Savings Rate                             OK     100.00% 0.112             
Secure Auth Login                        FAIL   98.58%  0.207  Bad Request
Validate Savings Rate Change             OK     100.00% 0.127             
Vested Balance                           OK     100.00% 0.157             


https://a.blazemeter.com/app/#/masters/36669958