简体   繁体   中英

What's the best way in PowerShell to parse these strings?

I'm getting two string passed into my script:

"Project1,Project2,Project3,Project4"
"web,batch,web,components"

The strings come from a tool in our DevOps toolchain and I have no control over the input format. String 1 could be any number of projects. String 2 will be the same number of entries with the "type" of the project in string 1.

I need to emit one string for each distinct type in the second string that contains the projects from the first string:

"Project1,Project3"
"Project2"
"Project4"

I know I can do it with a bunch of nested foreach loops. Is there a way to do this with a hashtable and/or arrays?

You can turn the original input strings into arrays with the -split operator:

$ProjectNames = "Project1,Project2,Project3,Project4" -split ','
$ProjectTypes = "web,batch,web,components" -split ','

Then create an empty hash table to contain the type-to-projectname mappings

$ProjectsByType = @{}

Finally iterate over the two arrays to group the project names by type:

for($i = 0; $i -lt $ProjectNames.Count; $i++){
    if(-not $ProjectsByType.ContainsKey($ProjectTypes[$i])){
        # Create key and entry as array if it doesn't already exist
        $ProjectsByType[$ProjectTypes[$i]] = @()
    }
    # Add the project to the appropriate project type key
    $ProjectsByType[$ProjectTypes[$i]] += $ProjectNames[$i]
}

Now you can produce your desired strings grouped by project type:

$ProjectsByType.Keys |ForEach-Object {
    $ProjectsByType[$_] -join ','
}

You could also create objects from the two arrays and use Group-Object to group them:

$Projects = for($i = 0; $i -lt $ProjectNames.Count; $i++){
    New-Object psobject -Property @{
        Name = $ProjectNames[$i]
        Type = $ProjectTypes[$i]
    }
}

$Projects |Group-Object -Property Type

This is more interesting if you want to do further processing of the projects, if you just need the strings the first approach is easier

There isn't really an elegant way of combining two arrays that way with built-in methods. A somewhat convoluted way would be the following:

$projects = $projectString -split ','
$types = $typeString -split ','
0..($projects.Count) | group { $types[$_] } | % { $projects[$_.Group] -join ',' }

However, this first generates indices into the arrays to group and format them later, which is inherently a bit iffy (and not very understandable). I tend to pre-process the data to actually reflect what I'm operating on:

$projects = $projectString -split ','
$types = $typeString -split ','
$projectsWithType = 0..($projects.Count) | % {
  [pscustomobject]@{
    Project = $projects[$_]
    Type = $types[$_]
  }
}
$projectsWithType | group Type | % { $_.Group -join ',' }

This makes the actual data munging task much clearer.

with only one search in first list

$projects = "Project1,Project2,Project3,Project4" -split ','
$types = "web,batch,web,components" -split ','

$linenumber = 0

$projects |%{New-Object psObject -Property @{Project=$_;TypeProject= $types[$linenumber]};$linenumber++} |
group TypeProject |
select Name, @{N="Projects";E={$_.Group.Project -join ","}}

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