I’m trying to manipulate some text that looks like this:
Users of FeatureA: (Total of 1 license issued; Total of 1 license in use)
Users of FeatureB: (Total of 3 license issued; Total of 2 license in use)
User.A ComputerA cryptictext (version) (ServerName/port processid), start Tue 10/30 7:20
User.B ComputerB cryptictext (version) (ServerName/port processid), start Tue 11/1 8:48
Users of FeatureC: (Total of 7 licenses issued; Total of 3 licenses in use)
User.A ComputerA cryptictext (version) (ServerName/port processid), start Tue 10/27 7:20
User.B ComputerB cryptictext (version) (ServerName/port processid), start Tue 10/30 8:48
User.C ComputerC cryptictext (version) (ServerName/port processid), start Tue 11/1 9:20
Users of FeatureD: (Total of 1 license issued; Total of 1 license in use)
Users of FeatureE: (Total of 1 license issued; Total of 1 license in use)
User.C ComputerC cryptictext (version) (ServerName/port processid), start Tue 11/1 6:32
Thanks to @kryzdoug from an earlier thread, I’ve reused the code to get this (ignore “Total of X license in use” as its not accurate … instead count number of User.X below each Feature):
License Total Used
FeatureA 1 0
FeatureB 3 2
FeatureC 7 3
FeatureD 1 0
FeatureE 1 1
You want to add hierarchical information into a structured data format. That’ll need more logic in your code and might be error prone. And - at least in the sample data you shared here - there are data sets missing. There is no User using the license of FeatureA or FeatureD?
I’d recommend trying to get another data source where you already have this information in a structured format.
Unfortunately, the datasource comes from a command line licensing tool and its output is not structured. The data I’ve pulled into $Lines are the only relevant information, namely license feature name and users who have checked it out.
FeatureA and FeatureD are correct in the sense that no user has checked out the license … hence its 0 under the Used column.
The end goal is to be able to view license usage and the Users who have checked it out. The “CheckedOut” column tells us who has been using it the longest (possibly being someone who has forgotten to check it back in before leaving the office).
Regex is hard, no question. Took me a while to get my head around $userspattern but got there in the end. Though I got stuck at understanding $Matches.{1,2,3} in the ordered hashtable. How does “-match $userspattern” turn into 3 different matches with the exact values (leaving out all the other detritus):
Users of FeatureA: (Total of 1 license issued; Total of 1 license in use)
Next, apologies for being spurious in the text output and explanation (I was trying to be generic) which led to some confusion.
I can’t make use of …
Total of 1 license in use
… as its not accurate (it includes reserved licenses). So “Used” needs to be the number of lines below “Users of Feature…” until the next “Users of Feature…”. Hence Feature{A,D} have 0 used.
Plus the actual text output of the users who have checked out licenses look more like this:
Users of FeatureB: (Total of 3 license issued; Total of 2 license in use)
john.buck COMPUTER012179 '9E081=DUF`D X@Qz^8v (v10.1) (SERVERNAME.domain.com/27000 5138), start Thu 10/27 12:31
jane.doe COMPUTER016046 '9E085@DRCaK$eFC6qX'vOI (v10.1) (SERVERNAME.domain.com/27000 2247), start Fri 10/28 6:06
Hence the regex $checkedpattern wouldn’t work in this situation. If I understand how $Matches.{1,2,3} elicits the correct values from the regex, I may be be able to have a go myself at the regex required for $checkedpattern.
When you post sample text it should be close to, if not exactly (sanitized of course) the same. No one can read your mind or see your screen. Advice/suggestions are given based on the information you provide.
$txt = @'
Users of FeatureA: (Total of 1 license issued; Total of 1 license in use)
Users of FeatureB: (Total of 3 license issued; Total of 2 license in use)
john.buck COMPUTER012179 '9E081=DUF`D X@Qz^8v (v10.1) (SERVERNAME.domain.com/27000 5138), start Thu 10/27 12:31
jane.doe COMPUTER016046 '9E085@DRCaK$eFC6qX'vOI (v10.1) (SERVERNAME.domain.com/27000 2247), start Fri 10/28 6:06
Users of FeatureC: (Total of 7 licenses issued; Total of 3 licenses in use)
User.A ComputerA cryptictext (version) (ServerName/port processid), start Tue 10/27 7:20
User.B ComputerB cryptictext (version) (ServerName/port processid), start Tue 10/30 8:48
User.C ComputerC cryptictext (version) (ServerName/port processid), start Tue 11/1 9:20
Users of FeatureD: (Total of 1 license issued; Total of 1 license in use)
Users of FeatureE: (Total of 1 license issued; Total of 1 license in use)
User.C ComputerC cryptictext (version) (ServerName/port processid), start Tue 11/1 6:32
'@
$userspattern = 'Users.+?(\S+):.+(\d+).+issued.+'
$checkedpattern = '\s+(\S+)\s+(\S+)\s+.+start\s+\w+\s+(\w.+)'
$output = $txt -split '(?=Users)' | ForEach-Object {
foreach($line in $_ -split '\r?\n'){
if($line -match $userspattern){
$current = [ordered]@{
License = $Matches.1
Total = $Matches.2
Used = 0
Checked = @()
}
}
elseif($line -match $checkedpattern){
$current.Used++
$current.Checked += [PSCustomObject]@{
Name = $Matches.1
Computer = $Matches.2
CheckedOut = $Matches.3
}
}
}
if($current){
[PSCustomObject]$current
}
Remove-Variable current -ErrorAction SilentlyContinue
}
$output | ConvertTo-Json
… so it’ll pick up double digit values. Went with the tabular format for better readability compared to json. And by some trial and error, I omitted the final else statement …
else{
[PSCustomObject]$current
}
… which output only licenses that had been checked out: