Biker John
Biker John

Reputation: 2711

Validate specific string

I would like to validate if user input string is in correct form for further processing / database update.

Form:

elephant1:elephant2:elephant3;cat1:cat2:cat3;unicorn1:unicorn2:unicorn3

: as separator between siblings and ; as separator between groups of siblings

Rules: There are ALWAYS 3 siblings, since it is meant just for personal bulk import, i just want to avoid mistakes with very long strings. As for the groups, there could be one or more, so group separator not obligatory. Siblings names are letters only with exception of underscore (_) for spaces when there are two or more words in a name.

i was thinking regex, but i am not very familiar with it. If there are any other, simpler ways to achieve this, please suggest.

Valid examples

N-number of groups, separated by semicolon, each of which containing exactly three (3) members separated by punctuation. As mentioned before, names are letters only, with exception of underscore as space for names with multiple words.

VALIDS:

john:mike:dave;jenny:helen:jessica

dog:cat:frog;car:boat:ship;house:flat:shack

meat:vegetable:fruit

UPDATE:

This is what i came up with while trying to understand your answers, it works fine so far

"/^(([a-z]+:[a-z]+:[a-z]+;?)+)$/"

Upgraded to Roman's answer

"/([a-z_]+:[a-z_]+:[a-z_]+;?)+/i"

allowing function to ignore spaces, tabs and allow underscores where items have multiple words.

Upvotes: 0

Views: 65

Answers (2)

RomanPerekhrest
RomanPerekhrest

Reputation: 92894

The solution using preg_match function with specific regex pattern:

$str = 'og:cat:frog;car:boat:ship;house:flat:shack';

if (preg_match("/([a-z_]+:[a-z_]+:[a-z_]+;?)+/i", $str)) {
    echo 'valid';
} else {
    echo 'invalid';
}

Upvotes: 1

Regular Jo
Regular Jo

Reputation: 5510

^(?:[a-zA-Z_]+:[a-zA-Z_]+:[a-zA-Z_]+(?:;(?!$)|$))+$ (demo, with multiline flag on)

^               # Anchors to beginning of string
(?:             # Opens non-capturing group
  [a-zA-Z_]+    # Any number of letters/underscore, one or more times
  :             # Literal :
  [a-zA-Z_]+    # Any number of letters/underscore, one or more times
  :             # Literal :
  [a-zA-Z_]+    # Any number of letters/underscore, one or more times
  (?:           # Opens non-capturing group
    ;           # Literal ;
    (?!$)       # Negative Lookahead, ensuring that semi-colons are not at the end of line
  |             # Or
    $           # End of string
  )             # Closes non-capturing group
)+              # Repeats overall non-capturing-group one or more times
$               # Anchors to end of string

You didn't specify if siblings could be 0 characters, if that's the case, change each [a-zA-Z_]+ to [a-zA-Z_]*

// PHP Code generated by Regex101.
$re = '/^(?:[a-zA-Z_]+:[a-zA-Z_]+:[a-zA-Z_]+(?:;(?!$)|$))+$/m';
$str = 'a_b:bread:stack_overflow;test:this_thing:jane;Get_me:h:down
 ab:bread:stack_overflow;test:this_thing:jane;Get_me:h:down
a_b:any other characters break it:stack_overflow;test:this_thing:jane;Get_me:h:down
a_b:bread:format_messed_up-test:this_thing:jane;Get_me:h:down
a_b:bread:stack_overflow;test:this_thing:jane;semi_colon_at_end;';

preg_match_all($re, $str, $matches);

// Print the entire match result
print_r($matches);

Upvotes: 1

Related Questions