Uranium-235 Posted July 2, 2012 Share Posted July 2, 2012 hey guys, long, long long long time no see. anyways, I stopped using ereg and am getting pretty good @ preg, but am running into a problem with one statement. what i'm trying to do is change a parsed text statement into a conditional statement, and am getting it done pretty well but one thing is not working take this string (this string has had variables replaced in to get to where it is now by earlier code, i'm going to eval() it) 5x11=8x11.5&6.3=6.3 but since I want to eval it, I need to turn the = into == other possible conditionals in these strings include < > <= >= of course if I did a simple str_replace, it would turn all other <= into <== which is a nono to be evaled so I do this $str = preg_replace('/[^\<\>][\=]{1}/m', '==', '5x11=8x11.5&6.3=6.3'); to try to say, match the =, but don't match any < or > in front of it and replace it with a == but it cuts the last numbers off of the successful == statement turning 5x11=8x11.5&6.3=6.3 into 5x1==8x11.5&6.==6.3 I essentially want the match to fail if there is a < or > front of the = sign, but its matching and taking the last number off if it does match any help? Quote Link to comment Share on other sites More sharing options...
joe92 Posted July 2, 2012 Share Posted July 2, 2012 I'm slightly confused by what you mean, is it turn = into == but only if it is not part of another operator, i.e. >=? $str = preg_replace('/[^\<\>][\=]{1}/m', '==', '5x11=8x11.5&6.3=6.3'); This part first, just for future reference, can be neatened up quite a bit. You don't need to escape those signs inside the character classes. Just the signs ']', '\', '-', '^' and whatever the closing delimiter is need to be escaped if using literally. Read the paragraph, 'Metacharacters Inside Character Classes', here. The repetition of 1 is also superfluous. You can just get rid of it. You also don't need to add a character class round a single character, =, you can remove that too. That makes the expression quite a bit easier to read: $str = preg_replace('/[^<>]=/m', '==', '5x11=8x11.5&6.3=6.3'); The reason the preg_replace is failing for your needs is because it is matching the symbol before the equal sign rather than just checking whether it exists or not. To fix this you need to use a negative lookbehind. A lookbehind (or lookahead) checks whether or not a character exists in the string but doesn't include it in the match. In this case we want to make sure the characters < or > do not exist before the equal sign. An annoying thing about the lookbehind is that is has to be of fixed length (a lookahead can be of unfixed length). This has tripped me up many a time in the past but I don't think that should be a problem here as it doesn't class alternation as varying length. Meaning we can use: $str = preg_replace('/(?<!<|>)=/m', '==', '5x11=8x11.5&6.3=6.3'); See it working here, http://codepad.viper-7.com/JUYovq. Hope that helps you, Joe Quote Link to comment Share on other sites More sharing options...
Uranium-235 Posted July 2, 2012 Author Share Posted July 2, 2012 thank you! it worked. Still confused by look aheads and behinds. preg is so much more complex than postix ereg Quote Link to comment Share on other sites More sharing options...
Uranium-235 Posted July 2, 2012 Author Share Posted July 2, 2012 I probably overdid all of it but hey it works. like this is what i'm taking in: S=8x16,S=8x10&V=10-50 and ending up with "5x11"=="8x16" || "5x11"=="8x10" && 6.3 >= 10 && 6.3 <= 50 which I will later eval() heres the code. i'm so worried about something going wrong I don't take any shortcuts, i'm sure I didn't have to use a decimil for each number i'm sure there is a flag for any number but not sure it applies to double type numbers $replace_arr = array('D' => $dia, 'L' => $len, 'V' => $volt, 'C' => $cap, 'R' => $ripple, 'E' => $esr, 'S' => $dia . 'x' . $len); foreach($replace_arr AS $replace => $replace_with) { $str = str_replace($replace, $replace_with, $str); } $str = str_replace('&', ' && ', $str); $str = preg_replace('/([0-9]{0,8}[\.]?[0-9]{0,8})[=]{1}([0-9]{0,8}[\.]?[0-9]{0,8})[-]{1}([0-9]{0,8}[\.]?[0-9]{0,8})/m', '$1 >= $2 && $1 <= $3', $str); $str = preg_replace('/(?<!<|>)=/m', '==', $str); $str = preg_replace('/([0-9]{0,8}[\.]?[0-9]{0,8})x([0-9]{0,8}[\.]?[0-9]{0,8})/m', "\"$1x$2\"", strtolower($str)); $str = str_replace(',', ' || ', $str); print($str . "<br/>\n"); Quote Link to comment Share on other sites More sharing options...
joe92 Posted July 2, 2012 Share Posted July 2, 2012 The flag for any number is \d You should refrain from doing repetition once, {1}, or placing a character class round a single character, [-]. They really are pointless and just mess up your pattern making it harder to bug find. The website I linked to in my previous post is a brilliant tutorial on regular expressions. If you don't understand something about them, like lookbehinds, then just read what it says. You'll find it helps. Quote Link to comment Share on other sites More sharing options...
Uranium-235 Posted July 4, 2012 Author Share Posted July 4, 2012 I think one thing I can also do is $str = str_replace('=', '==', $str); $str = str_replace('<==', '<=', $str); $str = str_replace('>==', '>=', $str); but i'm not sure how it would compare cpu intensity wise Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.