locked
Looping Regex RRS feed

  • Question


  • I don't know if there is a way to write a regex that would incorporate everything I need, but my question is about looping or an if/else statement using regex expressions.  Can you do something like that to look at one expression and match everything in it, then look at the other to  match everything else that the first one missed?  I'm not that great at these statements yet, but I'll give an example from an old script of mine.

    $input | % { if ($_ -match '(\w+)\s+(\w+)'){$results += New-Object psObject `
        -Property @{
             'Last Name'=$matches[1]
             'First Name'=$matches[2]]}}}

    I know it's a bit overkill, but I'm just curious if it can be done.  Basically, what I want to know is how you would write it, if it's possible, so it would look at the first expression, then look at a second one to match everything?  Expression doesn't really matter in the question, but here is another just for reference: (\w+)\s+(\w+\s\w+\.).  Like I said, I'm just curious, as I try and learn new things.  Thanks for any input. 

    Wednesday, May 4, 2016 3:33 AM

Answers

  • It's always right to be curious.

    But I'm not clear: Do you want to check an array of strings against one RegEx? Or do you want to check one string against an array of RegEx? Both can be done, of course. Since jrv posted the first case, I'll post the second.

    $patterns = "\w", "\d", "\w\d"
    
    $String = "abc2"
    
    $result = @()
    foreach($p in $patterns)
    {
        if($String -match $p){$result += "$String is matching $p"}
    }

    Of course, you can put this in another loop which iterates over an array of input strings.

    Futhermore, you can use -match operator in Where-Object

    $patterns | where{$String -match $_}

    I think, using where is the most comfortable way.

    Also jrv's code would be with using where:

    $myinput | where{$_ -match "(\w+)\s+(\w+)"} | foreach...

    Best wishes

    Christoph

    • Marked as answer by SharpKey Thursday, May 5, 2016 7:29 PM
    Wednesday, May 4, 2016 10:53 AM

All replies

  • Why not?

    $myinput = @('Joe Smith')
    $myinput | 
    	% {
    	if ($_ -match '(\w+)\s+(\w+)') {
    		New-Object psObject -Property @{ 'Last Name' = $matches[1]; 'First Name' = $matches[2] }
    	}
    }

    Everyone.  Meet 'SharpKey'.  He is stuck in Sharpsville until he learns the Dorian mode.  Things will get better.  The 'Dorian' is easier on the nerves and on the ear bones.

    It is a good idea to avoid using "$input" as it is a reserved variable.


    \_(ツ)_/

    • Proposed as answer by mukesh-kumar Wednesday, May 4, 2016 7:02 AM
    Wednesday, May 4, 2016 6:43 AM
  • It's always right to be curious.

    But I'm not clear: Do you want to check an array of strings against one RegEx? Or do you want to check one string against an array of RegEx? Both can be done, of course. Since jrv posted the first case, I'll post the second.

    $patterns = "\w", "\d", "\w\d"
    
    $String = "abc2"
    
    $result = @()
    foreach($p in $patterns)
    {
        if($String -match $p){$result += "$String is matching $p"}
    }

    Of course, you can put this in another loop which iterates over an array of input strings.

    Futhermore, you can use -match operator in Where-Object

    $patterns | where{$String -match $_}

    I think, using where is the most comfortable way.

    Also jrv's code would be with using where:

    $myinput | where{$_ -match "(\w+)\s+(\w+)"} | foreach...

    Best wishes

    Christoph

    • Marked as answer by SharpKey Thursday, May 5, 2016 7:29 PM
    Wednesday, May 4, 2016 10:53 AM
  • These all make sense, if they work the way I would expect them to.  I haven't tried, as I was just curious if it could be done.  However, in my example let's assume you have a file with first and last names, and you had the above regex, (\w+)\s+(\w+) to group those accordingly.  Well then some of those might have a middle initial, which would be filtered out of the return, so then you might create another like above, (\w+)\s+(\w+\s\w+\.) to capture those.  So, really I just wanted to know if you could use both to look at each line of the array with two or more regex expressions so that they return all the values, so in this scenario no name is left out.  Basically saying "well this one doesn't meet this expression, but it meets this one."  Which from what you are saying Chris, is that it can be done.

    Just trying to learn different ways of attacking a problem. 


    sharpkey

    Thursday, May 5, 2016 1:43 AM
  • Regular expressions can be very helpful, but the flexibility of this meta-language tends to lead to overthinking the problem. Read this first:

    Regular Expressions: Now You Have Two Problems

    Trying to come up with a single regular expression that finds all name variations is going to be "interesting," to say the least, and it will also likely lead to a very complex and difficult-to-understand regex that is very hard to troubleshoot.


    -- Bill Stewart [Bill_Stewart]

    Thursday, May 5, 2016 3:06 PM