Vitaliy Isikov
Vitaliy Isikov

Reputation: 3654

Regex pattern for matching a delimited string

I need a way to match the following pattern:

0hv05d_1a8198c8c430c2333fd6e49863f59f60_d41d8cd98f00b204e9800998ecf8427e_3600_3_25

Explained:

There are 6 sections separated by underscores. First section is always 6 [a-zA-Z0-9] characters. Second and third sections are MD5 hashes, so they will always be 32 [a-zA-Z0-9] characters each. Last 3 sections can only be numbers.

I'm using PHP preg_match() to do this.

Upvotes: 2

Views: 1233

Answers (6)

mickmackusa
mickmackusa

Reputation: 48070

Validation + Extraction

Strict, full string matching into capture groups using PCRE syntax and producing a string array. Demo

preg_match(
    '/^([a-z\d]{6})_([a-f\d]{32})_([a-f\d]{32})_(\d+)_(\d+)_(\d+)$/',
    $string,
    $m
);

Strict, full string matching into capture groups using POSIX syntax and producing a string array. Demo

preg_match(
    '/^([[:alnum:]]{6})_([[:xdigit:]]{32})_([[:xdigit:]]{32})_([[:digit:]]+)_([[:digit:]]+)_([[:digit:]]+)$/',
    $string,
    $m
);

Matching by format returning the capture count and producing individual scalar variables (strings and integers). Demo

sscanf(
    $string,
    '%6[a-z0-9]_%32[a-f0-9]_%32[a-f0-9]_%d_%d_%d',
    $one,
    $two,
    $three,
    $four,
    $five,
    $six
);

Matching by format returning a scalar array (strings and integers). Demo

sscanf(
    $string,
    '%6[a-z0-9]_%32[a-f0-9]_%32[a-f0-9]_%d_%d_%d',
)

Text Extraction Only

Simple splitting on the delimiter without any validation and producing a string array: Demo

var_export(explode('_', $string));

Upvotes: 0

daalbert
daalbert

Reputation: 1475

Edit- To be more complete you could do this:

if (preg_match('/[a-z0-9]{6}_[a-f0-9]{32}_[a-f0-9]{32}_\d+_\d+_\d+/i', $subject)) {
    # Successful match
} else {
    # Match attempt failed
}

I also to make it more concise replased [0-9] with the \d class, changed the matching of MD5 to just [a-f0-9], and I also changed [a-zA-Z0-9] to [a-z0-9] and included the /i for case insensitive.

If you really wanted to the expression could also be rewritten as:

/[a-z0-9]{6}(?:_[a-f0-9]{32}){2}(?:_\d+){3}/i

Upvotes: 1

AndersTornkvist
AndersTornkvist

Reputation: 2629

You could try:

<?php
$string = '0hv05d_1a8198c8c430c2333fd6e49863f59f60_d41d8cd98f00b204e9800998ecf8427e_3600_3_25';
if (preg_match('/([a-zA-Z0-9]{6})_([a-fA-F0-9]{32})_([a-fA-F0-9]{32})_([0-9]+)_([0-9]+)_([0-9]+)/',$string,$match)) {
    print_r( $match );
}
?>

Upvotes: 4

David Z
David Z

Reputation: 131780

Here's the shortest I can make it, based on your (somewhat incomplete) specifications:

preg_match('/[a-z\d]{6}(?:_[a-f\d]{32}){2}(?:_\d+){3}/i', $string);

This will match exactly six instances of a letter or digit; followed by an underscore and 32 hexadecimal digits, twice; followed by an underscore and any number of digits, 3 times. The /i at the end puts it into case-insensitive mode.

Upvotes: 8

colinross
colinross

Reputation: 2085

[a-zA-Z0-9]{6}_[a-f0-9]{32}_[a-f0-9]{32}_[0-9]+_[0-9]+_[0-9]+

ref: http://www.php.net/manual/en/reference.pcre.pattern.syntax.php

also, since php using PCRE (Pearl Compatible Regular Expressions) you can use this nifty cheat sheet: http://www.addedbytes.com/cheat-sheets/regular-expressions-cheat-sheet/

Upvotes: 0

Carlos Campderr&#243;s
Carlos Campderr&#243;s

Reputation: 23002

$string = "0hv05d_1a8198c8c430c2333fd6e49863f59f60_d41d8cd98f00b204e9800998ecf8427e_3600_3_25";
if (preg_match('/^([a-z0-9]{6})_([a-f0-9]{32})_([a-f0-9]{32})_([0-9]+)_([0-9]+)_([0-9]+)$/i', $string, $matches))
{
    echo "Match!<br />\n";
    echo "First: ".$matches[1]."<br />\n";
    echo "MD5 hashes: ".$matches[2]. " - ".$matches[3]."<br />\n";
    echo "numbers: ".$matches[4]. " - ".$matches[5]. " - ".$matches[6]."<br />\n";
}

notes:

  • md5 are just [a-f0-9], not [a-z0-9].
  • I put /i to case insensitive matches, instead of specifying [a-zA-Z] in every part.

Upvotes: 3

Related Questions