Partial String Replacement using PowerShell

2019-07-12 20:03发布

Problem

I am working on a script that has a user provide a specific IP address and I want to mask this IP in some fashion so that it isn't stored in the logs. My problem is, that I can easily do this when I know what the first three values of the IP typically are; however, I want to avoid storing/hard coding those values into the code to if at all possible. I also want to be able to replace the values even if the first three are unknown to me.

Examples:

10.11.12.50 would display as XX.XX.XX.50
10.12.11.23 would also display as XX.XX.XX.23

I have looked up partial string replacements, but none of the questions or problems that I found came close to doing this. I have tried doing things like:

# This ended up replacing all of the numbers
$tempString = $str -replace '[0-9]', 'X'

I know that I am partway there, but I aiming to only replace only the first 3 sets of digits so, basically every digit that is before a '.', but I haven't been able to achieve this.

Question

Is what I'm trying to do possible to achieve with PowerShell? Is there a best practice way of achieving this?

2条回答
闹够了就滚
2楼-- · 2019-07-12 20:08

TheIncorrigible1's helpful answer is an exact way of solving the problem (replacement only happens if 3 consecutive .-separated groups of 1-3 digits are matched.)

A looser, but shorter solution that replaces everything but the last .-prefixed digit group:

PS> '10.11.12.50' -replace '.+(?=\.\d+$)', 'XX.XX.XX'
XX.XX.XX.50

(?=\.\d+$) is a (positive) lookahead assertion ((?=...)) that matches the enclosed subexpression (a literal . followed by 1 or more digits (\d) at the end of the string ($)), but doesn't capture it as part of the overall match.

The net effect is that only what .+ captured - everything before the lookahead assertion's match - is replaced with 'XX.XX.XX'.

Applied to the above example input string, 10.11.12.50:

  • (?=\.\d+$) matches the .-prefixed digit group at the end, .50.

  • .+ matches everything before .50, which is 10.11.12.

  • Since the (?=...) part isn't captured, it is therefore not included in what is replaced, so it is only substring 10.11.12 that is replaced, namely with XX.XX.XX, yielding XX.XX.XX.50 as a result.

查看更多
霸刀☆藐视天下
3楼-- · 2019-07-12 20:25

Here's an example of how you can accomplish this:

Get-Content 'File.txt' |
  ForEach-Object { $_ = $_ -replace '\d{1,3}\.\d{1,3}\.\d{1,3}','xx.xx.xx' }

This example matches a digit 1-3 times, a literal period, and continues that pattern so it'll capture anything from 0-999.0-999.0-999 and replace with xx.xx.xx

查看更多
登录 后发表回答