none
Powershell search for a word and use the next word RRS feed

  • Question

  • Here is the skinny.  I am trying to easily part through a event log of print jobs.  I export it to a CSV, grab only the events that pertain to what I need but I am stuck there.  Here is a sample of what I need help with.

    Microsoft Word - Test Print owned by user1 on computer1 was printed on printer1 through port

    Obviously document name, user1, computer1 and printer1 will be different in almost every case.  How do I parse through this and grab the username, computer and printer.  I was thinking search for "owned by", but how do I grab the name?

    Thanks for the help.

    Thursday, April 23, 2015 7:41 PM

Answers

  • ok now I am running into another issue.  Apparently the nuances of splitting by word seems to be los on me.

    when I do

    foreach ($job in $printjob) {       

    $test = $job.split("owned by")       

    echo $test

    }


    It will then split the line by each and ever "o", "w", "n", "e", "d", etc.....  I even tried $test = $job.split("'owned by'").  Any ideas?

    I feel like I should explain why this is happening.

    When you call $job.Split(), you're calling the .NET Split() method of the object System.String.

    If you look at the overloads of split (i.e., all the different ways you can call String.Split) - link here https://msdn.microsoft.com/en-us/library/system.string.split%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396 -, you'll notice that the only way of calling String.Split() with a single parameter is if you pass a char[], an array of characters.

    Now, if you were coding in C# or VB.NET and you did... String.Split("owned by"), you'd get an error saying that it's expecting a char[] but you gave it a string.

    Powershell however is a bit 'smarter' and it tries to accommodate... It knows that the method expects a char[] and it knows you gave it a string, but it also knows how to convert it to a char[], so it does that, and that's what the method String.Split() receives.

    And what happens when the method String.Split() receives a char[]? It splits on every single character in that char[], as you've seen :)

    How to fix it? Well, there are two overloads that accept a string[], so you can use those. Now here's an interesting fact...

    In the same way that PowerShell converted a string to a char[] to accommodate the needs of the method you were calling, it can also convert a string into a string[], so you could do this:

    $job.Split("owned by", [System.StringSplitOptions]::None)

    You're passing it a string... and a [StringSplitOptions] object, so you expect it to call the third overload from the page I provided earlier.

    But if you run it... you still get the same stuff as before! What gives?

    Well, seeing as in this particular case there is an overload that receives char[] and another that receives string[] and you passed a string, which means PowerShell will always have to convert it into something anyway... You have no control over what PowerShell will decide to convert the string to. It could convert to char[] or to string[]. In this case, because the definition of the char[] method appears before the string[], that gets picked.

    So, finally... how to force PowerShell to pick the string[] overload? Well, don't give it a choice!

    $job.Split([string[]] "owned by", [System.StringSplitOptions]::None)

    So here I'm casting the string into a string[] before it gets passed to the method, so PowerShell does not need to perform any conversion itself and everything is right with the world.

    Hope this helps :)

    • Proposed as answer by Mike Laughlin Friday, April 24, 2015 7:22 PM
    • Marked as answer by Trey_b Friday, April 24, 2015 7:25 PM
    Friday, April 24, 2015 7:15 PM
  • When you split the string

    Microsoft Word - Test Print owned by user1 on computer1 was printed on printer1 through port

    by "owned by " then you get two strings:
    Microsoft Word - Test Print
    user1 on computer1 was printed on printer1 through port

    To get the user's name you split the second string by " " and take the first element. This method assumes that your users' account names have no embedded spaces.



    • Edited by Frederik Long Thursday, April 23, 2015 8:20 PM
    • Marked as answer by Trey_b Thursday, April 23, 2015 9:33 PM
    • Unmarked as answer by Trey_b Friday, April 24, 2015 6:38 PM
    • Proposed as answer by Mike Laughlin Friday, April 24, 2015 6:51 PM
    • Marked as answer by Trey_b Friday, April 24, 2015 7:25 PM
    Thursday, April 23, 2015 8:18 PM

All replies

  • When you split the string

    Microsoft Word - Test Print owned by user1 on computer1 was printed on printer1 through port

    by "owned by " then you get two strings:
    Microsoft Word - Test Print
    user1 on computer1 was printed on printer1 through port

    To get the user's name you split the second string by " " and take the first element. This method assumes that your users' account names have no embedded spaces.



    • Edited by Frederik Long Thursday, April 23, 2015 8:20 PM
    • Marked as answer by Trey_b Thursday, April 23, 2015 9:33 PM
    • Unmarked as answer by Trey_b Friday, April 24, 2015 6:38 PM
    • Proposed as answer by Mike Laughlin Friday, April 24, 2015 6:51 PM
    • Marked as answer by Trey_b Friday, April 24, 2015 7:25 PM
    Thursday, April 23, 2015 8:18 PM
  • You know....  I have been doing a lot of splits with powershell and for some strange reason I did not think to utilize it here......  I think I have been working to hard.. 

    Thanks for the remind ;)

    Thursday, April 23, 2015 9:33 PM
  • ok now I am running into another issue.  Apparently the nuances of splitting by word seems to be los on me.

    when I do

    foreach ($job in $printjob) {       

    $test = $job.split("owned by")       

    echo $test

    }


    It will then split the line by each and ever "o", "w", "n", "e", "d", etc.....  I even tried $test = $job.split("'owned by'").  Any ideas?

    Friday, April 24, 2015 6:42 PM
  • Hi,

    Use -split instead of .Split().

    $str = 'Microsoft Word - Test Print owned by user1 on computer1 was printed on printer1 through port'
    
    (($str -split 'owned by')[1].Trim() -split ' ')[0]


    Don't retire TechNet! - (Don't give up yet - 13,225+ strong and growing)

    Friday, April 24, 2015 6:47 PM
  • ok now I am running into another issue.  Apparently the nuances of splitting by word seems to be los on me.

    when I do

    foreach ($job in $printjob) {       

    $test = $job.split("owned by")       

    echo $test

    }


    It will then split the line by each and ever "o", "w", "n", "e", "d", etc.....  I even tried $test = $job.split("'owned by'").  Any ideas?

    I feel like I should explain why this is happening.

    When you call $job.Split(), you're calling the .NET Split() method of the object System.String.

    If you look at the overloads of split (i.e., all the different ways you can call String.Split) - link here https://msdn.microsoft.com/en-us/library/system.string.split%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396 -, you'll notice that the only way of calling String.Split() with a single parameter is if you pass a char[], an array of characters.

    Now, if you were coding in C# or VB.NET and you did... String.Split("owned by"), you'd get an error saying that it's expecting a char[] but you gave it a string.

    Powershell however is a bit 'smarter' and it tries to accommodate... It knows that the method expects a char[] and it knows you gave it a string, but it also knows how to convert it to a char[], so it does that, and that's what the method String.Split() receives.

    And what happens when the method String.Split() receives a char[]? It splits on every single character in that char[], as you've seen :)

    How to fix it? Well, there are two overloads that accept a string[], so you can use those. Now here's an interesting fact...

    In the same way that PowerShell converted a string to a char[] to accommodate the needs of the method you were calling, it can also convert a string into a string[], so you could do this:

    $job.Split("owned by", [System.StringSplitOptions]::None)

    You're passing it a string... and a [StringSplitOptions] object, so you expect it to call the third overload from the page I provided earlier.

    But if you run it... you still get the same stuff as before! What gives?

    Well, seeing as in this particular case there is an overload that receives char[] and another that receives string[] and you passed a string, which means PowerShell will always have to convert it into something anyway... You have no control over what PowerShell will decide to convert the string to. It could convert to char[] or to string[]. In this case, because the definition of the char[] method appears before the string[], that gets picked.

    So, finally... how to force PowerShell to pick the string[] overload? Well, don't give it a choice!

    $job.Split([string[]] "owned by", [System.StringSplitOptions]::None)

    So here I'm casting the string into a string[] before it gets passed to the method, so PowerShell does not need to perform any conversion itself and everything is right with the world.

    Hope this helps :)

    • Proposed as answer by Mike Laughlin Friday, April 24, 2015 7:22 PM
    • Marked as answer by Trey_b Friday, April 24, 2015 7:25 PM
    Friday, April 24, 2015 7:15 PM
  • You can grab document, user, computer and printer all at once using -match:

    $Message = 'Microsoft Word - Test Print owned by user1 on computer1 was printed on printer1 through port'
    if ($Message -match '(?<Document>.+) owned by (?<User>.+) on (?<Computer>.+) was printed on (?<Printer>.+) through') {
        $Matches.Document    
        $Matches.User
        $Matches.Computer
        $Matches.Printer
    }


    Sunday, April 26, 2015 6:01 PM