Appleoddity
Appleoddity

Reputation: 1181

Is this a bug in powershell's TrimStart?

Forgive me if I am wrong to be frustrated about this. But, this is why I hate trying to do anything remotely complex in a scripting language like PowerShell. It's a never ending battle with unpredictability.

So, here it is:

PS C:\WINDOWS\system32> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      15063  632 

PS C:\WINDOWS\system32> $testpath = "\\a-server-unc\home\auser\Outlook Data\archive1 - Copy.pst"

PS C:\WINDOWS\system32> $(Split-path -path $testpath -Parent)
\\a-server-unc\home\auser\Outlook Data #Ok - Looks good

PS C:\WINDOWS\system32> $(Split-path -path $testpath -Parent).TrimStart("\\a-server-unc")
home\auser\Outlook Data   # Where did my slash go?

PS C:\WINDOWS\system32> $(Split-path -path $testpath -parent).TrimStart("\\a-server-unc\home")
Outlook Data  # Wait - What the...

PS C:\WINDOWS\system32> $testpath
\\a-server-unc\home\auser\Outlook Data\archive1 - Copy.pst # Yep - I'm not insane. Powershell is eating my characters.

PS C:\WINDOWS\system32> $testpath = "\\a-server-unc\home\aloser\Outlook Data\archive1 - Copy.pst"  #Let's try changing the string a little

PS C:\WINDOWS\system32> $(Split-path -path $testpath -Parent).TrimStart("\\a-server-unc\home")
loser\Outlook Data   # I must be insane

PS C:\WINDOWS\system32> $(Split-path -path $testpath -Parent).TrimStart("`\`\a-server-unc`\home") #Certainly escaping the slashes will fix this?
loser\Outlook Data   # Nope, more hours wasted on unpredictable behavior

Now clearly there is some strange, "perfectly normal" behavior here, but I'm getting a little tired of Powershell eating my strings.

What's the magic potion here?

Upvotes: 1

Views: 3898

Answers (2)

C. Helling
C. Helling

Reputation: 1402

See TrimStart() documentation here: https://msdn.microsoft.com/en-us/library/system.string.trimstart.aspx

In particular, note that TrimStart() takes a character array as input, not a string (as you seem to be expecting):

public string TrimStart(
    params char[] trimChars
)

So TrimStart() is removing characters, not an entire string.

See, for example, the output of:

$testpath = "hhhhhhhhhhhhhhelloooooooo".TrimStart("h")

It outputs:

elloooooooo

The solution is to use the Replace() function instead.

One such way to do that:

$testpath = "\\a-server-unc\home\auser\Outlook Data\archive1 - Copy.pst"
$basepath = "\\a-server-unc\"
[regex]$pattern = [regex]::escape($basepath)
# pattern is regex version of string you want to replace
# .replace("string to replace", "replacing string", numberOfReplacements)
# i.e. only replace the 1st instance
$newPath = $pattern.replace($testpath, [string]::Empty, 1)

Outputs for $newPath:

home\auser\Outlook Data\archive1 - Copy.pst

Upvotes: 1

Sage Pourpre
Sage Pourpre

Reputation: 10323

That's the expected behavior.

As per documentation

String.TrimStart Method (Char())

Removes all leading occurrences of a set of characters specified in an array from the current String object. - source

To trim a contiguous string, you could use -replace using regex

"\a-server-unc\home\user\a-server-unc\Outlook Data\archive1" -replace "^\\a-server-unc\\",''

The output would result in

home\user\a-server-unc\Outlook Data\archive1

The key character being to include the ^ to signify that the occurrence is right after the start of of the line and not anywhere (that's why the second occurence of my replace stayed.)

If you prefer to avoid regex, you would need something like this:

function TrimStart([String]$InputObject,[String]$Value){
    if ($InputObject.StartsWith($Value)) {
        return $InputObject.Substring($value.Length,$InputObject.Length - $value.Length)
    }
    else{
        return $InputObject
    }
}

Here's is the difference between the two in action. $ConceptString = 'This is a very long string that also happens to be a complete sentence !!!'

write-host $ConceptString.TrimStart('This is a very long string') -ForegroundColor Cyan
#Output: ppens to be a complete sentence !!!
Write-host $(TrimStart $ConceptString -Value 'This is a very long string')  -ForegroundColor Green
#output: that also happens to be a complete sentence !!!

Upvotes: 3

Related Questions