2

I'm attempting to create a PowerShell script to pick particular lines from large log files. Using Select-String, I've gotten the data down to just the rows I need in a multiline string. Now I'd like to further massage it to return only the ID numbers from those rows, in a single, comma-delimited string.

Current code:

if (Select-String $SearchFile -Pattern $SearchString -Quiet) {
    Write-Host "Error message found"
    $body += Select-String $SearchFile -Pattern $SearchString -Context 1,0 |
             foreach {$_.Context.DisplayPreContext} | Out-String
    Send-MailMessage (email_info_here) -Body $body
} else {
    Write-Host "No errors found"
}

Currently returning the following string:

INFO | Creating Batch for 197988 | 03/24/2016 02:10 AM
INFO | Creating Batch for 202414 | 03/24/2016 02:10 AM
INFO | Creating Batch for 173447 | 03/24/2016 02:10 AM

Would like to get the output to the format:

197988, 202414, 173447
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
D.Espo
  • 23
  • 1
  • 3
  • At the moment it looks like you are pushing all of the lines you find through `Out-String` when creating **$body**. I suggest leaving out the `Out-String` part which should keep **$body** as an array rather than a multi-line string. Some of the answers below would work better on an array (esp. using `foreach` to loop through each line). – Charlie Joynt Mar 24 '16 at 21:00

3 Answers3

2

If Body contains those lines, then you just need to split and index into the column that has our data.

$body | ForEach-Object {$psitem.Split()[5]}
197988
202414
173447  

In this sample, we call ForEach-Object to make a little code block to execute on each line. Then, we call the line's $split() method to split on spaces. Then we just index into the fifth column, using $psitem[5].

Assuming you want to save the lines back into $body again, just add $body = to the front of line 1.

Edit: Multi-line-string vs. Array

In the original post, the $body variable was created with Out-String as the last command in the pipeline. This would make it a single multi-line string. Leaving out the | Out-String part would make $body an array of strings. The latter (an array) is easier to work with and is what the answer above assumes, since it is easy to loop through each line in the array with foreach.

Converting between the two is done like this:

$string = @"
INFO | Creating Batch for 197988 | 03/24/2016 02:10 AM
INFO | Creating Batch for 202414 | 03/24/2016 02:10 AM
INFO | Creating Batch for 173447 | 03/24/2016 02:10 AM
"@

$array = @(
"INFO | Creating Batch for 197988 | 03/24/2016 02:10 AM"
"INFO | Creating Batch for 202414 | 03/24/2016 02:10 AM"
"INFO | Creating Batch for 173447 | 03/24/2016 02:10 AM"
)

$array_from_string = $string -split("`n")
$string_from_array = $array | Out-String

In order for the answer to work you need to make sure that $body is an array, else you will only get one ID number:

$string | Foreach-Object {$psitem.Split()[5]}
197988
Charlie Joynt
  • 4,411
  • 1
  • 24
  • 46
FoxDeploy
  • 12,569
  • 2
  • 33
  • 48
1

Replace Out-String with a Where-Object filter that matches the number part of each result line, extract the number submatch, and join the result:

$body += (Select-String $SearchFile -Pattern $SearchString -Context 1,0 |
         ForEach-Object { $_.Context.DisplayPreContext } |
         Where-Object { $_ -match 'for (\d+) \|' } |
         ForEach-Object { $matches[1] }) -join ', '
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
0

This might be a dirty way to do it, but it works:

#This can also be your variable
$log = gc "C:\[log path here]"

#Remove beginning of string up to ID
$log = $log -replace '(.*?)for ' , ""

#Select first 6 characters since all IDs shown are 6 characters
$logIDs = @()
foreach($line in $log){
    $logIDs += $line.substring(0,6)
}

### At this point $logIDs contains all IDs, now we just need to comma separate them ###

$count = 1
foreach($ID in $logIDs){
    if($count -eq $logIDs.count){
        $result += $ID
    }
    else{
        $result += $ID+", "
        $count++
    }
}

#Here are your results separated by commas
$result

Hope this helps, let me know if you need any type of variation.

nkasco
  • 326
  • 1
  • 2
  • 13