Jump to content

[SOLVED] preg_match a character, except where it's wrapped in braces


Mark Baker

Recommended Posts

I'm not particularly good with regular expressions, but I need to do a preg_match to see if a string contains an instance of a particular character where it isn't wrapped in square braces.

 

e.g. If I was testing for the character 'd'

"dd-MMM-yyyy"

    should return a TRUE because d is in the string, and there are no square braces

"[$-F800]dddd\,\ mmmm\ dd\,\ yyyy"

    should return a TRUE because there is a d in the string outside of the square braces

"[Red]dddd\,\ mmmm\ dd\,\ yyyy"

    should return a TRUE because there is a d in the string outside of the square braces, even though there is also a d within the square braces

"[Red]#,##0.00;[Green]-#,##0.00"

    should return a FALSE because there is no d in the string outside of the square braces

"#,##0.00"

    should return a FALSE because there is no d in the string irrespective of the fact that there are no square braces either

 

Previously, I've simply been using stripos to check whether a 'd' exists, but returning a false if there are square braces as well, but this is no longer an adequate check, so preg_match seemed a better more flexible alternative

 

 

I also have a loop which executes this script for several characters in an array, 'd' being just one such character. If any of these characters exist (outside of square braces), then a True is returned. False is only return if none of the characters in the array exist (outside of the square braces) in the tested string.

I'm sure a preg_match could also allow me to test for any of the characters in the array in a single call, rather than needing to loop.

 

However, I'm way out of my depth with regexp. Any help would be much appreciated

Link to comment
Share on other sites

Looks like some of my examples are setting message formatting

"dd-MMM-yyyy"
    should return a TRUE because d is in the string, and there are no square braces
"[$-F800]dddd\,\ mmmm\ dd\,\ yyyy" 
    should return a TRUE because there is a d in the string outside of the square braces
"[Red]dddd\,\ mmmm\ dd\,\ yyyy"
    should return a TRUE because there is a d in the string outside of the square braces, even though there is also a d within the square braces
"[Red]#,##0.00;[Green]-#,##0.00"
    should return a FALSE because there is no d in the string outside of the square braces
"#,##0.00"
    should return a FALSE because there is no d in the string irrespective of the fact that there are no square braces either

 

Currently I'm using a preg_replace first to strip out the [] and their content before doing the preg_match

$formatValue = preg_replace('/\[(.*?)\]/','',$formatValue);
foreach ($possibleCharacters as $possibleCharacter) {
if (preg_match('/'.$possibleCharacter.'/i',$formatValue)) {
	return True;
}
}
return False;

Link to comment
Share on other sites

For this example, I just lumped some of your samples into an array and check from there. So, if I understand this correctly

 

$str = array('"dd-MMM-yyyya"', '"[$-F800a]dddd\,\ mmmm\ dd\,\ yyyy"', '"#,##0.00;-#,##0.00"', '"[dda]-MMM-yyyy"', '"dd\yyyy\a[d]\mmmm"');
$match = NULL;
foreach($str as $val){
   if(!preg_match('#\[.*?d.*?\]#', $val) && strpbrk($val, 'd')){
      $match[] = $val;
   }
}
echo '<pre>'.print_r($match, true);

 

Output:

Array
(
    [0] => "dd-MMM-yyyya"
    [1] => "[$-F800a]dddd\,\ mmmm\ dd\,\ yyyy"
)

 

Am I on the right track?

Link to comment
Share on other sites

I see what you're trying to do: if there isn't a 'd' in [], but there is still a 'd' somewhere in the string, then accept.

But I need a positive if there is a 'd' in the non-bracketed part of the string, even if there is a bracketed 'd' as well; so I need a valid match for "dd\yyyy\a[d]\mmmm" as well.

 

My preg_replace to strip the brackets and their content followed by preg_match to test for the character does work as expected... I was hoping it would be possible to do the entire test in a single preg_match though.

Link to comment
Share on other sites

try

<?php
$test[] = "dd-MMM-yyyy";
//    should return a TRUE because d is in the string, and there are no square braces
$test[] = "[$-F800]dddd\,\ mmmm\ dd\,\ yyyy"; 
//    should return a TRUE because there is a d in the string outside of the square braces
$test[] = "[Red]dddd\,\ mmmm\ dd\,\ yyyy";
//    should return a TRUE because there is a d in the string outside of the square braces, even though there is also a d within the square braces
$test[] = "[Red]#,##0.00;[Green]-#,##0.00";
//    should return a FALSE because there is no d in the string outside of the square braces
$test[] = "#,##0.00";
$char = 'd';
$pattern = '/(^|\])[^\[]*'.$char.'/';
foreach ($test as $t){
echo $t,' -> ', preg_match($pattern,$t) ? 'TRUE' : 'FALSE', "<br />\n";
}
?>

Link to comment
Share on other sites

Thanks sasa

That works a treat.

 

I can even test for all possible variations of $char by setting it as '[dmyhis]', which will return a true if any of those characters are in the string being tested, which is what I needed; so I don't need to loop through my array of individual valid characters any more.

Link to comment
Share on other sites

it doesn't work if you have nested brace ('[a[bc]d]')
Appreciate that, but that shouldn't ever occur. I know that my string to search should always be cleanly generated, because I have an implicit trust in the developers of MS Excel, and of those applications capable of writing Excel format files :-)

 

Thanks again for the solution.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.