简体   繁体   中英

Regular expression, letter used even/odd-numbered times

Thread's title might be little bit misleading, but I didnt find out any better way to name it. I want to find a way using regex to look for words that contains only letters x and y, but x has to be used an even-numbered times and y has to be used odd-numbered times.

I would know how to do that with two regex's.

This one checks if there is an even number of x (and at least two):

/^(y*xy*x)+y*$/

And this one checks if there is an odd number of y (and at least one):

/^(x*yx*y)*x*yx*$/

Both will match only strings exclusively formed of x an y.

I've tested this in my editor:

(?=([^x]*x[^x]*x[^x]*)*)(?=([^y]*y[^y]*y[^y]*)*[^y]*y[^y]*)

This will find substrings, so you may want to add space, beginning, end of line characters:

[^\s](?=([^x]*x[^x]*x[^x]*)*)(?=([^y]*y[^y]*y[^y]*)*[^y]*y[^y]*)[$\s]

To break it down, [^x]*x[^x]*x[^x]* will grab all not-x, until it finds the first x, then grabs whatever following non-x until it finds the second x, then again grabs whatever else follows until another x. This is enclosed in ( )* so that it is repeated unlimited number of times, so that it finds all pairs of x's. If there is an odd x left over (odd x's), the regex will not be able to match that single x left. Similarly for the y case, it matches all pairs of y's, then makes sure there is a single y left followed by all not-y's. I used ?= so that it matches but does not capture, so that we can check for x's then in the same string check for y's.

Here's a tested JavaScript example function implementing a single regex that meets your requirements. I am assuming that zero is an acceptable (even) number of Xs. The regex is documented in a multi lined comment.

function has_even_X_odd_Y_word(text) {
/*#!(?#!js\/i re_even_x_odd_y Rev:20170125_2100)
    # Match word having even count of X and odd count of Y.
    \b       # Anchor to start of word.
    # First assert odd, non-zero count of Ys in this word.
    (?=      # Assert odd count of Y.
      (?:    # Zero or more or more Y pairs.
        x*y  # Optional Xs preceeding 1st Y.
        x*y  # Optional Xs preceeding 2nd Y.
      )*     # End zero or more Y pairs.
      x*yx*  # Optional Xs around last (odd) Y.
      \b     # Anchor to end of word.
    )        # End assert odd count of Y.
    # Match even number of Xs (can be zero = even).
    (?:      # Zero or more X pairs.
      y*x    # Optional Ys preceeding 1st X.
      y*x    # Optional Ys preceeding 2nd X.
    )*       # End zero or more X pairs.
    y*       # Optional Ys after last (even) X.
    \b       # Anchor to end of word.
!#*/
    var re_even_x_odd_y = /\b(?=(?:x*yx*y)*x*yx*\b)(?:y*xy*x)*y*\b/i;
    if (re_even_x_odd_y.test(text)) { return true; }
    return false;
} // End has_even_X_odd_Y_word().

The function returns true if a matching word is found in the passed text and false otherwise.

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