33

I'm trying to spit the string with a delimiter, which is a string:

$string = "5637144576, messag<>est<<>>5637145326, 1<<>>5637145328, 0"
$separator = "<<>>"
$string.Split($separator)

As the result of splitting I get:

5637144576, messag

est



5637145326, 1



5637145328, 0

Instead of

5637144576, messag<>est
5637145326, 1
5637145328, 0

When I try to use overloaded split which accepts string[]:

$string = "5637144576, messag<>est<<>>5637145326, 1<<>>5637145328, 0"
$separator = @("<<>>")
$string.Split($separator)

But I get next error:

Cannot convert argument "0", with value: "System.Object[]", for "Split" to type "System.Char[]": "Cannot convert value "<<>>" to type "System.Char". Error: "String must be exactly one character long.""

Does someone knows how to split string by string?

7 Answers7

51

The -split operator uses the string to split, instead of a chararray like Split():

$string = "5637144576, messag<>est<<>>5637145326, 1<<>>5637145328, 0"
$separator = "<<>>"
$string -split $separator

5637144576, messag<>est
5637145326, 1
5637145328, 0

If you want to use the Split() method with a string, you need the $seperator to be a stringarray with one element, and also specify a stringsplitoptions value. You can see this by checking its definition:

$string.Split

OverloadDefinitions                                                                                
-------------------                                                                                
string[] Split(Params char[] separator)                                                            
string[] Split(char[] separator, int count)                                                        
string[] Split(char[] separator, System.StringSplitOptions options)                                
string[] Split(char[] separator, int count, System.StringSplitOptions options)                     

#This one
string[] Split(string[] separator, System.StringSplitOptions options)      
string[] Split(string[] separator, int count, System.StringSplitOptions options)


$string = "5637144576, messag<>est<<>>5637145326, 1<<>>5637145328, 0"
$separator = [string[]]@("<<>>")
$string.Split($separator, [System.StringSplitOptions]::RemoveEmptyEntries)

5637144576, messag<>est
5637145326, 1
5637145328, 0

EDIT: As @RomanKuzmin pointed out, -split splits using regex-patterns by default. So be aware to escape special characters (ex. . which in regex is "any character"). You could also force simplematch to disable regex-matching like:

$separator = "<<>>"
$string -split $separator, 0, "simplematch"

Read more about -split here.

Laurel
  • 5,965
  • 14
  • 31
  • 57
Frode F.
  • 52,376
  • 9
  • 98
  • 114
  • `est` should be preserved. He seems to want to split by any character of `<<>>` (that is, along `<` and `>`) – John Dvorak May 08 '13 at 07:57
  • sry, didn't see est in the sample of the output you wanted ^^ see updated answer – Frode F. May 08 '13 at 08:00
  • do you know, is possible to return only not empty string? –  May 08 '13 at 08:02
  • 1
    see last update. it explains the `Split()` methods behaviour too – Frode F. May 08 '13 at 08:11
  • 3
    "the -split operator uses the literal string to split" -- The -split operator uses a regular expression by default (without the SimpleMatch option). In this example it does not matter but generally speaking it does. – Roman Kuzmin Jul 26 '14 at 05:49
  • +1 I actually never read about split. Never tried to split with `.` etc. Just learned something new. You could actually use a scriptblock too, which is awesome! :) But in this case with the pattern `<<>>` it uses the exact string. Will update the answer. – Frode F. Jul 26 '14 at 07:16
  • some alternatives for .split() `$string.split([string[]]'<<>>','none')` or `$string.split((,'<<>>'),0)` – js2010 Oct 22 '22 at 19:39
2

Instaed of using Split method, you can use split operator. So your code will be like this:

$string -split '<<>>'
Piotr Stapp
  • 19,392
  • 11
  • 68
  • 116
1

Sometimes PowerShell looks exactly like C# and at others, well you know...

It could also be used thus:

# A dummy text file
$text = @'
abc=3135066977,8701416400

def=8763026853,6433607660

xyz=3135066977,9878763344
'@ -split [Environment]::NewLine,[StringSplitOptions]"RemoveEmptyEntries"

"`nBefore `n------`n"

$text

"`nAfter `n-----`n"

# Do whatever with this
foreach ($line in $text)
{
    $line.Replace("3135066977","6660985845")
}
Vince Ypma
  • 65
  • 5
1

EDIT 2020-05-23: I've moved my code to GitHub, here, where I've made updates to cover a few edge cases: https://github.com/franklesniak/PowerShell_Resources/blob/master/Split-StringOnLiteralString.ps1


You can use the -split operator, but it expects RegEx. Furthermore, the -split operator is only available on Windows PowerShell v3+, so we need a different method if you want something that is universally compatible with all versions of PowerShell.

A [regex] object has a Split() method that can handle this as well, but again, it expects RegEx as the "splitter". To get around this, we can use a second [regex] object and call the Escape() method to convert our literal string "splitter" into escaped RegEx.

Wrapping all this up into an easy to use function that works back to PowerShell v1 and also works on PowerShell Core 6.x.

function Split-StringOnLiteralString
{
    trap
    {
        Write-Error "An error occurred using the Split-StringOnLiteralString function. This was most likely caused by the arguments supplied not being strings"
    }

    if ($args.Length -ne 2) `
    {
        Write-Error "Split-StringOnLiteralString was called without supplying two arguments. The first argument should be the string to be split, and the second should be the string or character on which to split the string."
    } `
    else `
    {
        if (($args[0]).GetType().Name -ne "String") `
        {
            Write-Warning "The first argument supplied to Split-StringOnLiteralString was not a string. It will be attempted to be converted to a string. To avoid this warning, cast arguments to a string before calling Split-StringOnLiteralString."
            $strToSplit = [string]$args[0]
        } `
        else `
        {
            $strToSplit = $args[0]
        }

        if ((($args[1]).GetType().Name -ne "String") -and (($args[1]).GetType().Name -ne "Char")) `
        {
            Write-Warning "The second argument supplied to Split-StringOnLiteralString was not a string. It will be attempted to be converted to a string. To avoid this warning, cast arguments to a string before calling Split-StringOnLiteralString."
            $strSplitter = [string]$args[1]
        } `
        elseif (($args[1]).GetType().Name -eq "Char") `
        {
            $strSplitter = [string]$args[1]
        } `
        else `
        {
            $strSplitter = $args[1]
        }

        $strSplitterInRegEx = [regex]::Escape($strSplitter)

        [regex]::Split($strToSplit, $strSplitterInRegEx)
    }
}

Now, using the earlier example:

PS C:\Users\username> Split-StringOnLiteralString "5637144576, messag<>est<<>>5637145326, 1<<>>5637145328, 0" "<<>>"
5637144576, messag<>est
5637145326, 1
5637145328, 0

Volla!

Frank Lesniak
  • 560
  • 1
  • 5
  • 18
0

The following should be what you need:

 $string -Split $separator

This produces:

5637144576, messag<>est
5637145326, 1
5637145328, 0
David Martin
  • 11,764
  • 1
  • 61
  • 74
0

This work well, when I declare a string. While getting content from a file it does not work as expected. You can try this out with the same content within a file.

  • Please add more result set or sample data with your response. it will be make your answer more explanatory for others. – Er. Amit Joshi May 30 '22 at 18:05
  • This does not really answer the question. If you have a different question, you can ask it by clicking [Ask Question](https://stackoverflow.com/questions/ask). To get notified when this question gets new answers, you can [follow this question](https://meta.stackexchange.com/q/345661). Once you have enough [reputation](https://stackoverflow.com/help/whats-reputation), you can also [add a bounty](https://stackoverflow.com/help/privileges/set-bounties) to draw more attention to this question. - [From Review](/review/late-answers/31897824) – Ravindu Jun 05 '22 at 07:56
0

This actually works in powershell 7.

$string = "5637144576, messag<>est<<>>5637145326, 1<<>>5637145328, 0"
$separator = "<<>>"
$string.Split($separator)

5637144576, messag<>est
5637145326, 1
5637145328, 0

Powershell 7 actually has a new .split() overload that more closely matches a string as a first argument. Surprisingly, the options 2nd argument can be left off, with a default 'None' value.

public string[] Split (string? separator, 
  StringSplitOptions options = System.StringSplitOptions.None);

https://learn.microsoft.com/en-us/dotnet/api/system.string.split?view=net-7.0#system-string-split(system-string-system-stringsplitoptions)

js2010
  • 23,033
  • 6
  • 64
  • 66