Extract the number before a file extension (.ps1)

2020-04-20 06:46发布

A cmdlet that creates a file returns a block of text, and in that is the name of the file. The file has a format of string[number].ps1, but the number is random, so I would like to extract that number and store it in a variable.

Block of text for reference:

  +         ~~~~~\nA 'using' statement must appear before any other statements in\
    \ a script.\nAt C:\\Packages\\Plugins\\Microsoft.CPlat.Core.RunCommandWindows\\\
    1.1.3\\Downloads\\script35.ps1:20 char:8\n+         using Microsoft.Build.Framework;\n\
    +              ~\nMissing using directive\nAt C:\\Packages\\Plugins\\Microsoft.CPlat.Core.RunCommandWindows\\\
    1.1.3\\Downloads\\script35.ps1:20 char:3\n+         using Microsoft.Build.Framework;\n\
    +         ~~~~~\nA 'using' statement must appear before any other statements in\
    \ a script.\nAt C:\\Packages\\Plugins\\Microsoft.CPlat.Core.RunCommandWindows\\\
    1.1.3\\Downloads\\script35.ps1:21 char:8\n+         using Microsoft.Build.Utilities;\n\
    +              ~\nMissing using directive\nAt C:\\Packages\\Plugins\\Microsoft.CPlat.Core.RunCommandWindows\\\
    1.1.3\\Downloads\\script35.ps1:21 char:3\n+         using Microsoft.Build.Utilities;\n\
    +         ~~~~~\nA 'using' statement must appear before any other statements in\

I thought $result -match '\d\d+(?=\.\w+)' would work, but it only returned the lines the number was found on, instead of just the number.

1条回答
可以哭但决不认输i
2楼-- · 2020-04-20 07:34

With a collection (as opposed to a single value) as the LHS, the -match operator:

  • acts as a filter - i.e. returns the subarray of matching elements rather than a Boolean

  • does not populate the automatic $Matches variable with the matching operator's results.

That's why your output comprised the matching lines as a whole.


To return only the matching parts, you can use a switch statement with the -Regex option to loop over your array of lines, in which case $Matches is populated for each input line:

# Array of sample lines.
# For illustrative purposes I've tweaked the `script<number>.ps1`
# tokens to have successive numbers.
$lines = @'
 +         ~~~~~\nA 'using' statement must appear before any other statements in\
    \ a script.\nAt C:\\Packages\\Plugins\\Microsoft.CPlat.Core.RunCommandWindows\\\
    1.1.3\\Downloads\\script35.ps1:20 char:8\n+         using Microsoft.Build.Framework;\n\
    +              ~\nMissing using directive\nAt C:\\Packages\\Plugins\\Microsoft.CPlat.Core.RunCommandWindows\\\
    1.1.3\\Downloads\\script36.ps1:20 char:3\n+         using Microsoft.Build.Framework;\n\
    +         ~~~~~\nA 'using' statement must appear before any other statements in\
    \ a script.\nAt C:\\Packages\\Plugins\\Microsoft.CPlat.Core.RunCommandWindows\\\
    1.1.3\\Downloads\\script37.ps1:21 char:8\n+         using Microsoft.Build.Utilities;\n\
    +              ~\nMissing using directive\nAt C:\\Packages\\Plugins\\Microsoft.CPlat.Core.RunCommandWindows\\\
    1.1.3\\Downloads\\script38.ps1:21 char:3\n+         using Microsoft.Build.Utilities;\n\
    +         ~~~~~\nA 'using' statement must appear before any other statements in\
'@ -split '\r?\n'

# Perform the matching, line by line,
# and output each line's matching part,
# resulting in an array of strings.
# Prepend 
#     $result = 
# to store the array in a variable.
switch -Regex ($lines) {
  '\d+(?=\.\w+)' { $Matches[0] } # to extract only the *1st* match,
                                   # append `; break` inside the { ... }
}

The above yields:

35
36
37
38

Note that switch also supports reading lines directly from a file, using the -File option
(switch -Regex -File $filePath { ... }).

查看更多
登录 后发表回答