简体   繁体   中英

PHP preg_match with regular expression: only single hyphens and spaces between words

How can I allow single hyphens and single spaces only within words but not at the beginning or at the end of the words?

if(!preg_match('/^[a-zA-Z0-9\-\s]+$/', $pg_tag))
    {
        $error = true;
        echo '<error elementid="pg_tag" message="TAGS - only alphanumbers and hyphens are allowed."/>';
    }

I don't want to accept these inputs below

---stack---over---flow---
stack-over-flow- stack-over-flow2
   stack    over    flow

but only these are acceptable,

stack-over-flow stack-over-flow2 stack-over-flow3
stack over flow
stacoverflow

Thanks.

$aWords = array(
    'a',
    '---stack---over---flow---',
    '   stack    over    flow',
    'stack-over-flow',
    'stack over flow',
    'stacoverflow'
);

foreach($aWords as $sWord) {
    if (preg_match('/^(\w+([\s-]\w+)?)+$/', $sWord)) {
        echo 'pass: ' . $sWord . "\n";
    } else {
        echo 'fail: ' . $sWord . "\n";
    }
}

And the output:

pass: a
fail: ---stack---over---flow---
fail:    stack    over    flow
pass: stack-over-flow
pass: stack over flow
pass: stacoverflow

A breakdown of the Regex:

^             # Match from the very beginning of the string
(             # Start Group
    \w+       # At least one "word" character
    (         # Start Subgroup
       [\s-]  # A single space or a dash
       \w+    # At least one "word" character
    )?        # End Subgroup is optional
)+            # End group - allow it multiple times
$             # Match until the very end of the string

To accept character or digit with space in between them. In case of only space it fails the test or do not accept only.

This Regular expression accept string like "Home Work" but failed with " ".

var pattern = /^(?=.*\S)[.+a-z0-9A-Z-.#:!*$^_|?` ]+$/;
     return pattern.test(value);

This returns true if string is accepted.

With respect to the comments: Another idea is to "normalize" the input, ie reducing all consecutive spaces and dashes to one and removing them from the beginning and end:

$pg_tag = preg_replace(array('/\s+/', '/-+/'), 
                       array(' ', '-'), 
                       trim($pg_tag, ' -'));

Reference: preg_replace , trim

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