Reputation: 3050
substring complains when I try to limit a string to 10 characters which is not 10 or more characters in length. I know I can test the length but I would like to know if there is a single cmdlet which will do what I need.
PS C:\> "12345".substring(0,5)
12345
PS C:\> "12345".substring(0,10)
Exception calling "Substring" with "2" argument(s): "Index and length must refer to a location within the string.
Parameter name: length"
At line:1 char:18
+ "12345".substring( <<<< 0,10)
Upvotes: 23
Views: 77064
Reputation: 872
Just a different spin on Dmitry's answer. Turning his code into an extension method has the downside of making it unclear that it's a third party addition but on the upside it reads much nicer if you're doing many of these operations and it's chainable with other methods.
Update-TypeData -TypeName 'System.String' `
-MemberType 'ScriptMethod' `
-MemberName 'Take' `
-Value {
param( [int] $length = $this.Length )
return $this.Substring(0, [Math]::Min($length, $this.Length)) } `
-Force
# Example
'Foo$Bar!Baz__-123'.Replace('$Bar', '').Take(5)
# Returns: Foo!B
Upvotes: 0
Reputation: 1
How about padding first.
$s = "12345"
$s.PadRight(10).Substring(0,10).TrimEnd() # returns "12345"
Upvotes: 0
Reputation: 1994
Do you need exactly a cmdlet? I wonder why you don't like getting length. If it's part of a script, then it looks fine.
$s = "12345"
$s.substring(0, [System.Math]::Min(10, $s.Length))
Upvotes: 40
Reputation: 190
The previous answers didn't suit my purposes (no offence!) so I took Denomales suggestion above and rolled it into a function which I thought I'd share:
function Trim-Length {
param (
[parameter(Mandatory=$True,ValueFromPipeline=$True)] [string] $Str
, [parameter(Mandatory=$True,Position=1)] [int] $Length
)
$Str[0..($Length-1)] -join ""
}
Example usages:
"1234567" | Trim-Length 4 # returns: "1234"
"1234" | Trim-Length 99 # returns: "1234"
Upvotes: 2
Reputation: 15000
Using the substring function has it's limitations and requires you to first capture the length of the string. Granted this does work you can do it without that limitation.
The following will return the first 5 characters of the string
"1234567890"[0..4] -join "" # returns the string '12345'
And this will work on strings that are shorter than desired length
"1234567890"[0..1000] -join "" # returns the string '1234567890'
Upvotes: 33
Reputation: 31
You can load and use other libraries and use their string functions, for example the visual basic string functions work nicely for what you want to do
call once per session
>[void][reflection.assembly]::LoadWithPartialName("microsoft.visualbasic")
then use various vb string functions
>[microsoft.visualbasic.strings]::left("12345",10)
12345
or
>[microsoft.visualbasic.strings]::mid("12345",1,10)
12345
Upvotes: 3
Reputation: 3050
Thanks to Dmitry for the answer, I turned it into a function and made it so it is 1 based as opposed to 0 based.
function acme-substr ([string]$str, $start, $end) {
$str.substring($start-1, [System.Math]::Min($str.Length-1, $end))
}
> $foo="0"*20
> $foo
00000000000000000000
> acme-substr $foo 1 5
00000
Upvotes: 0