简体   繁体   中英

PowerShell Regex - word with wildcards and commas

Trying to do a replace on what I understand to be a simple operation but hitting a wall.

I can replace a word with a comma on the end:

$firstval = 'ssonp,RDPNP,LanmanWorkstation,webclient,MfeEpePcNP,PRNetworkProvider'

($firstval) -replace 'webclient+,',''

ssonp,RDPNP,LanmanWorkstation,MfeEpePcNP,PRNetworkProvider

But haven't been able to work out how to add a wildcard in the word, or how I'd have multiple words with wildcards proceeded by a comma, eg:

w* client+,* fee*, etc

(spaces added to stop being interpreted as formatting within the question)

Played with a few permeations and attempted to use examples from other questions without any luck.

The -replace operator takes a regular expression as its first parameter. You seem to be confusing wildcards and regular expressions. Your pattern w*client+,*fee*, , though a valid regular expression, seems to be intended to use wildcards.

The regular expression equivalent of the * wildcard is .* , where . means "any character" and * means "0 or more occurrences". Thus, the regular expression equivalent of w*client, would be w.*client, , and, similarly the regular expression equivalent of *fee*, would be .*fee.*, . Since the string to be searched has comma-separated values, however, we don't want our patterns to include "any character" ( .* ) but rather "any character but comma" ( [^,]* ). Therefore, the patterns to use become w[^,]*client, and [^,]*fee[^,]*, , respectively.

To search for both words in a string, separate the two patterns with | . The following builds such a pattern and tests it against strings with a match in various locations:

# Match w*client or *fee*
$wordPattern = 'w[^,]*client|[^,]*fee[^,]*';
# Match $wordPattern and at most one comma before or after
$wordWithAdjacentCommaPattern = '({0}),?|,({0})$' -f $wordPattern;

"`$wordWithAdjacentCommaPattern: $wordWithAdjacentCommaPattern";
# Replace single value
'webclient', `
# Replace first value
'webclient,middle,last', `
# Replace middle value
'first,webclient,last', `
# Replace last value
'first,middle,webclient' `
    | ForEach-Object -Process { '"{0}" => "{1}"' -f $_, ($_ -replace $wordWithAdjacentCommaPattern); };

This outputs the following:

$wordWithAdjacentCommaPattern: (w[^,]*client|[^,]*fee[^,]*),?|,(w[^,]*client|[^,]*fee[^,]*)$
"webclient" => ""
"webclient,middle,last" => "middle,last"
"first,webclient,last" => "first,last"
"first,middle,webclient" => "first,middle"

A non-regex alternative you might consider would be to split your input string into individual values, filter out values that match certain wildcards, and reassemble what's left into comma-separated values:

(
    'ssonp,RDPNP,LanmanWorkstation,webclient,MfeEpePcNP,PRNetworkProvider' -split ',', -1, 'SimpleMatch' `
        | Where-Object { $_ -notlike 'w*client' -and $_ -notlike '*fee*'; } `
) -join ',';

By the way, you used the regular expression webclient+, to match and remove the text webclient, from your string (looks like the HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order\\ProviderOrder registry value). Just a note that, with the + , that will search for the literal text webclien followed by 1 or more occurrences of t followed by the literal text , . Thus, that will match webclientt, , webclienttt, , webclientttttttttt, , etc. as well webclient, . If you are only interested in matching webclient, then you can just use the pattern webclient, (no + ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM