40

I want to give the possibility to match string with wildcard *.

Example

$mystring = 'dir/folder1/file';
$pattern = 'dir/*/file';

stringMatchWithWildcard($mystring,$pattern);  //> Returns true

Example 2:

$mystring = 'string bl#abla;y';
$pattern = 'string*y'; 

stringMatchWithWildcard($mystring,$pattern);  //> Returns true

I thought something like:

function stringMatch($source,$pattern) {
    $pattern = preg_quote($pattern,'/');        
    $pattern = str_replace( '\*' , '.*?', $pattern);   //> This is the important replace
    return (bool)preg_match( '/^' . $pattern . '$/i' , $source );
}

Basically replacing * to .*? (considering in *nix environment * matches empty string) ©vbence

Any improvments/suggests?

// Added return (bool) because preg_match returns int

6 Answers 6

62

There is no need for preg_match here. PHP has a wildcard comparison function, specifically made for such cases:

fnmatch()

And fnmatch('dir/*/file', 'dir/folder1/file') would likely already work for you. But beware that the * wildcard would likewise add further slashes, like preg_match would.

Sign up to request clarification or add additional context in comments.

2 Comments

hi mario. fnmatches has some other feature like []. I just need * as "special char"
fnmatch is not supported on non-POSIX systems. (I see that php5.3+ also supports windows now). So this is not always the best way
4

You should just use .* instead.

$pattern = str_replace( '*' , '.*', $pattern);   //> This is the important replace

Edit: Also your ^ and $ were in the wrong order.

<?php

function stringMatchWithWildcard($source,$pattern) {
    $pattern = preg_quote($pattern,'/');        
    $pattern = str_replace( '\*' , '.*', $pattern);   
    return preg_match( '/^' . $pattern . '$/i' , $source );
}

$mystring = 'dir/folder1/file';
$pattern = 'dir/*/file';

echo stringMatchWithWildcard($mystring,$pattern); 



$mystring = 'string bl#abla;y';
$pattern = 'string*y'; 

echo stringMatchWithWildcard($mystring,$pattern); 

Working demo: http://www.ideone.com/mGqp2

6 Comments

I don't know if I want to give the possibility to match this 'dir//file' with 'dir/*/file'
.* is greedy, it will eat all the rest of your string, no just the minimal number of characters to continue with the patters. So if you have anything after .* the result will be always false.
I thought that was exactly what you wanted to do with .+? from your description.
@vbence preg_match('/.*a/', 'aa') ?
Ok it seems match will give the same results.
|
3
.+?

Causes non-greedy matching for all characters. This is NOT equal to "*" becuase it will not match the empty string.

The following pattern will match the empty string too:

.*?

so...

stringMatchWithWildcard ("hello", "hel*lo"); // will give true

7 Comments

do you think I should allow for empty string? Consider dir too: 'dir//file' matching 'dir/*/file' ?
If you want it to work analogous to how OS shells work, then you have to allow for the empty string. Just try echo > hello followed by dir hello* in windows or ls hello* in *nix. In this context * matches the empty string.
It would be polite to give a comment with your -1.
ah nice! thanks for the *nix comparsion! (also i didnt -1 your answer, no reason for me to do that)
@yes123 Yep, I know, not accusing. :)
|
2

You're mixing up ending ($) and beginning (^). This:

preg_match( '/$' . $pattern . '^/i' , $source );

Should be:

preg_match( '/^' . $pattern . '$/i' , $source );

Comments

0

The one problem you'll have is that the call to preg_quote() will escape the asterisk character. Given that, your str_replace() will replace the *, but not the escape character in front of it.

Therefore you should change the str_replace('*' ..) with str_replace('\*'..)

1 Comment

i missed that from the documetnatnion my bad. fixed
0
$pattern = str_replace( '\*' , '.+?', $pattern);   // at least one character

1 Comment

Please add some explanation to your code - have a look at the other answers to this question for some inspiration

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.