Re: [PHP] ereg_replace with user defined function?
10 okt 2006 kl. 19.25 skrev Roman Neuhauser: # [EMAIL PROTECTED] / 2006-10-09 22:01:34 +0200: Thank you Ilaria and Roman for your input. I did not know that preg is able to deal with PCRE patterns. preg is obviously short for Perl REGular expressions, while PCRE positively means Perl-Compatible Regular Expressions. The regexp syntax from Perl is a superset of POSIX extended regexps, so anything ereg_ function accept will be good for preg_ as well (but beware of pattern delimiters). Thanks for the info. I didn't know that. As a matter of fact I came up with the following solution (if someone is interested): What problem does it solve? I mean, why are you trying to avoid preg_replace_callback() in the first place? Maybe because I didn't know better? Initially, I was using ereg_replace for replacing metric numbers with imperial ones. But obviously, ereg_replace replaces all instances in the given text string. A text containing more than one instance of the same unit, was replaced by the calculated replacement string of the first finding. So I had to think about other ways to do this - which brought me to preg_replace_callback (as I already said - I didn't know that preg takes POSIX patterns as well). Would you suggest a different way? Would it be faster to do the replacement with preg_replace_callback compared to the function I wrote? A page like this one: http://www.nikehydraulics.com/products/ product_chooser_gb.php?productMaingroup=5productSubgroup=33 .. gets converted within 0.32 / 0.34 seconds which I think is quite ok. /frank the function takes a text and an array with converters like: $converters[] = array ( metric = mm, imperial = in, ratio = 0.039370079, round = 1 ); $converters[] = array ( metric = m, imperial = ft, ratio = 3.280839895, round = 1 ); function convertTextString ( $text, $convertTable ) { # this function takes a text string, searches for numbers to convert, convert those numbers and returns # the complete text again. if ( !ereg ( [[:digit:]], $text ) ) // if the text does not contain any numbers, return the text as it is { return $text; } foreach ( $convertTable as $convertKey = $convertUnit ) { $pattern = ((\d{1,10}[,|.]*\d{0,10})*(\s)(%s)([$|\s|.|,|\)|/]+| $)); // this regex looks for a number followed by white space, followed by the metric unit, followed by a closing character like ., , or ) $pattern = sprintf ( $pattern, $convertUnit['metric'] ); while ( preg_match ( $pattern, $text, $matches ) ) { $matches[1] = str_replace ( ,, ., $matches[1] ); // in case numbers are written like 6,6 m, we need to replace , with . // because we do not want to return 0, we have to make shure that the new value is not zero. $itterator = 0; do { $value = round ( ( $matches[1] * $convertUnit['ratio'] ), $convertUnit['round'] + $itterator ); ++$itterator; } while ( $value == 0 || $itterator == 10 ); $replacement = $value . $2 . $convertUnit['imperial'] . $4; $text = preg_replace ( $pattern, $replacement, $text, 1 ); } } return $text; } -- How many Vietnam vets does it take to screw in a light bulb? You don't know, man. You don't KNOW. Cause you weren't THERE. http://bash.org/?255991 -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] ereg_replace with user defined function?
# [EMAIL PROTECTED] / 2006-10-11 09:52:51 +0200: 10 okt 2006 kl. 19.25 skrev Roman Neuhauser: # [EMAIL PROTECTED] / 2006-10-09 22:01:34 +0200: Thank you Ilaria and Roman for your input. I did not know that preg is able to deal with PCRE patterns. preg is obviously short for Perl REGular expressions, while PCRE positively means Perl-Compatible Regular Expressions. The regexp syntax from Perl is a superset of POSIX extended regexps, so anything ereg_ function accept will be good for preg_ as well (but beware of pattern delimiters). Thanks for the info. I didn't know that. NP, glad to be of help. The relationship is quite obvious if you look at both syntaxes. As a matter of fact I came up with the following solution (if someone is interested): What problem does it solve? I mean, why are you trying to avoid preg_replace_callback() in the first place? Maybe because I didn't know better? Well your question mentioned preg_replace_callback() so I thought maybe there was something about the function you didn't like. Initially, I was using ereg_replace for replacing metric numbers with imperial ones. But obviously, ereg_replace replaces all instances in the given text string. A text containing more than one instance of the same unit, was replaced by the calculated replacement string of the first finding. So I had to think about other ways to do this - which brought me to preg_replace_callback (as I already said - I didn't know that preg takes POSIX patterns as well). Would you suggest a different way? Would it be faster to do the replacement with preg_replace_callback compared to the function I wrote? Definitely, and probably by several orders of magnitude. A page like this one: http://www.nikehydraulics.com/products/ product_chooser_gb.php?productMaingroup=5productSubgroup=33 .. gets converted within 0.32 / 0.34 seconds which I think is quite ok. If the time covers only the conversion then it's quite terrible. Looking at the convertTextString() function below there's a few obvious optimizations waiting to be done, and... turning the foreach into a single preg_replace_callback() is the one that begs implementing the most (the code below's been tested and works): class convertor { const SI_to_Imperial = 0; const Imperial_to_SI = 1; function convert($amount, $unit, $direction) { return sprintf( whatever '%s' of '%s' is in the Imperial system , $amount , $unit ); } } function callbackSI2IS(array $SIspec) { return convertor::convert( $SIspec[1] , $SIspec[2] , convertor::SI_to_Imperial ); } $p = '~ ((?:\d+[,|.])*\d+) # amount \s* (m{1,2}\b) # meters or millis ~x'; echo preg_replace_callback( $p , 'callbackSI2IS' , file_get_contents('php://stdin') ); the function takes a text and an array with converters like: $converters[] = array ( metric = mm, imperial = in, ratio = 0.039370079, round = 1 ); $converters[] = array ( metric = m, imperial = ft, ratio = 3.280839895, round = 1 ); function convertTextString ( $text, $convertTable ) { # this function takes a text string, searches for numbers to convert, convert those numbers and returns # the complete text again. if ( !ereg ( [[:digit:]], $text ) ) // if the text does not contain any numbers, return the text as it is { return $text; } foreach ( $convertTable as $convertKey = $convertUnit ) { $pattern = ((\d{1,10}[,|.]*\d{0,10})*(\s)(%s)([$|\s|.|,|\)|/]+| $)); // this regex looks for a number followed by white space, followed by the metric unit, followed by a closing character like ., , or ) $pattern = sprintf ( $pattern, $convertUnit['metric'] ); while ( preg_match ( $pattern, $text, $matches ) ) { $matches[1] = str_replace ( ,, ., $matches[1] ); // in case numbers are written like 6,6 m, we need to replace , with . // because we do not want to return 0, we have to make shure that the new value is not zero. $itterator = 0; do { $value = round ( ( $matches[1] * $convertUnit['ratio'] ), $convertUnit['round'] + $itterator ); ++$itterator; } while ( $value == 0 || $itterator == 10 ); $replacement = $value . $2 . $convertUnit['imperial'] . $4;
Re: [PHP] ereg_replace with user defined function?
Thanks again for your suggestions. Actually, - believe it or not - I have never written a class (I am still learning PHP after three years working with that language). So I am not quite sure of the benefits of your class. One thing I do realise is the benefit of replacing the foreach loop with a single preg_replace_callbak. Let me try to sum up: With a preg_replace_callback I am able to look for a pattern like: a number ( float or integer ) followed by whitespace followed by one, two, three or more characters, followed by a closing character. e.g.: ((\d{1,10}[,|.]*\d{0,10})*(\s)(\D{1,3})([$|\s|.|,|\)|/]+| $)) (untested) If preg finds a match, it will pass an array to the specified function. In that function I evaluate the unit, see if it is in my array containing the conversion table. If that is the case, calculate the new value and return everything. Right? I will get back with this new approach. BTW, 0.32/0.34 seconds includes: calling the original html page from an outside server, loading this page into the DOM parser, walking through every table and every text string on that page. Convert everything necessary (the converter array contains about 14 metric - imperial converters) replace all converted DOM nodes and output everything. The metric / imperial calculations / replacements take between 0.00054 and 0.005 seconds per table cell / text string. /frank 11 okt 2006 kl. 13.39 skrev Roman Neuhauser: # [EMAIL PROTECTED] / 2006-10-11 09:52:51 +0200: 10 okt 2006 kl. 19.25 skrev Roman Neuhauser: # [EMAIL PROTECTED] / 2006-10-09 22:01:34 +0200: Thank you Ilaria and Roman for your input. I did not know that preg is able to deal with PCRE patterns. preg is obviously short for Perl REGular expressions, while PCRE positively means Perl-Compatible Regular Expressions. The regexp syntax from Perl is a superset of POSIX extended regexps, so anything ereg_ function accept will be good for preg_ as well (but beware of pattern delimiters). Thanks for the info. I didn't know that. NP, glad to be of help. The relationship is quite obvious if you look at both syntaxes. As a matter of fact I came up with the following solution (if someone is interested): What problem does it solve? I mean, why are you trying to avoid preg_replace_callback() in the first place? Maybe because I didn't know better? Well your question mentioned preg_replace_callback() so I thought maybe there was something about the function you didn't like. Initially, I was using ereg_replace for replacing metric numbers with imperial ones. But obviously, ereg_replace replaces all instances in the given text string. A text containing more than one instance of the same unit, was replaced by the calculated replacement string of the first finding. So I had to think about other ways to do this - which brought me to preg_replace_callback (as I already said - I didn't know that preg takes POSIX patterns as well). Would you suggest a different way? Would it be faster to do the replacement with preg_replace_callback compared to the function I wrote? Definitely, and probably by several orders of magnitude. A page like this one: http://www.nikehydraulics.com/products/ product_chooser_gb.php?productMaingroup=5productSubgroup=33 .. gets converted within 0.32 / 0.34 seconds which I think is quite ok. If the time covers only the conversion then it's quite terrible. Looking at the convertTextString() function below there's a few obvious optimizations waiting to be done, and... turning the foreach into a single preg_replace_callback() is the one that begs implementing the most (the code below's been tested and works): class convertor { const SI_to_Imperial = 0; const Imperial_to_SI = 1; function convert($amount, $unit, $direction) { return sprintf( whatever '%s' of '%s' is in the Imperial system , $amount , $unit ); } } function callbackSI2IS(array $SIspec) { return convertor::convert( $SIspec[1] , $SIspec[2] , convertor::SI_to_Imperial ); } $p = '~ ((?:\d+[,|.])*\d+) # amount \s* (m{1,2}\b) # meters or millis ~x'; echo preg_replace_callback( $p , 'callbackSI2IS' , file_get_contents('php://stdin') ); the function takes a text and an array with converters like: $converters[] = array ( metric = mm, imperial = in, ratio = 0.039370079, round = 1 ); $converters[] = array ( metric = m, imperial = ft, ratio = 3.280839895, round = 1 ); function convertTextString ( $text, $convertTable ) { # this function takes a text string, searches for numbers to convert, convert those numbers and returns # the complete text again. if ( !ereg (
Re: [PHP] ereg_replace with user defined function?
# [EMAIL PROTECTED] / 2006-10-11 14:28:21 +0200: Actually, - believe it or not - I have never written a class (I am still learning PHP after three years working with that language). So I am not quite sure of the benefits of your class. Nevermind then. I don't know how to fit my experience into a short email, so I'm not going to explain it, just replace the class with whatever pays the bill. Let me try to sum up: With a preg_replace_callback I am able to look for a pattern like: a number ( float or integer ) followed by whitespace followed by one, two, three or more characters, followed by a closing character. e.g.: ((\d{1,10}[,|.]*\d{0,10})*(\s)(\D{1,3})([$|\s|.|,|\)|/]+|$)) (untested) that's wrong unless you want e. g. these to match: 1|2|3|4 (^) 00|,. [EMAIL PROTECTED] If preg finds a match, it will pass an array to the specified function. In that function I evaluate the unit, see if it is in my array containing the conversion table. If that is the case, calculate the new value and return everything. Right? Yes. I will get back with this new approach. BTW, 0.32/0.34 seconds includes: calling the original html page from an outside server, loading this page into the DOM parser (...) ok then -- How many Vietnam vets does it take to screw in a light bulb? You don't know, man. You don't KNOW. Cause you weren't THERE. http://bash.org/?255991 -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] ereg_replace with user defined function?
# [EMAIL PROTECTED] / 2006-10-09 22:01:34 +0200: Thank you Ilaria and Roman for your input. I did not know that preg is able to deal with PCRE patterns. preg is obviously short for Perl REGular expressions, while PCRE positively means Perl-Compatible Regular Expressions. The regexp syntax from Perl is a superset of POSIX extended regexps, so anything ereg_ function accept will be good for preg_ as well (but beware of pattern delimiters). As a matter of fact I came up with the following solution (if someone is interested): What problem does it solve? I mean, why are you trying to avoid preg_replace_callback() in the first place? the function takes a text and an array with converters like: $converters[] = array ( metric = mm, imperial = in, ratio = 0.039370079, round = 1 ); $converters[] = array ( metric = m, imperial = ft, ratio = 3.280839895, round = 1 ); function convertTextString ( $text, $convertTable ) { # this function takes a text string, searches for numbers to convert, convert those numbers and returns # the complete text again. if ( !ereg ( [[:digit:]], $text ) ) // if the text does not contain any numbers, return the text as it is { return $text; } foreach ( $convertTable as $convertKey = $convertUnit ) { $pattern = ((\d{1,10}[,|.]*\d{0,10})*(\s)(%s)([$|\s|.|,|\)|/]+| $)); // this regex looks for a number followed by white space, followed by the metric unit, followed by a closing character like ., , or ) $pattern = sprintf ( $pattern, $convertUnit['metric'] ); while ( preg_match ( $pattern, $text, $matches ) ) { $matches[1] = str_replace ( ,, ., $matches[1] ); // in case numbers are written like 6,6 m, we need to replace , with . // because we do not want to return 0, we have to make shure that the new value is not zero. $itterator = 0; do { $value = round ( ( $matches[1] * $convertUnit['ratio'] ), $convertUnit['round'] + $itterator ); ++$itterator; } while ( $value == 0 || $itterator == 10 ); $replacement = $value . $2 . $convertUnit['imperial'] . $4; $text = preg_replace ( $pattern, $replacement, $text, 1 ); } } return $text; } -- How many Vietnam vets does it take to screw in a light bulb? You don't know, man. You don't KNOW. Cause you weren't THERE. http://bash.org/?255991 -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] ereg_replace with user defined function?
Thank you Ilaria and Roman for your input. I did not know that preg is able to deal with PCRE patterns. As a matter of fact I came up with the following solution (if someone is interested): the function takes a text and an array with converters like: $converters[] = array ( metric = mm, imperial = in, ratio = 0.039370079, round = 1 ); $converters[] = array ( metric = m, imperial = ft, ratio = 3.280839895, round = 1 ); function convertTextString ( $text, $convertTable ) { # this function takes a text string, searches for numbers to convert, convert those numbers and returns # the complete text again. if ( !ereg ( [[:digit:]], $text ) ) // if the text does not contain any numbers, return the text as it is { return $text; } foreach ( $convertTable as $convertKey = $convertUnit ) { $pattern = ((\d{1,10}[,|.]*\d{0,10})*(\s)(%s)([$|\s|.|,|\)|/]+| $)); // this regex looks for a number followed by white space, followed by the metric unit, followed by a closing character like ., , or ) $pattern = sprintf ( $pattern, $convertUnit['metric'] ); while ( preg_match ( $pattern, $text, $matches ) ) { $matches[1] = str_replace ( ,, ., $matches[1] ); // in case numbers are written like 6,6 m, we need to replace , with . // because we do not want to return 0, we have to make shure that the new value is not zero. $itterator = 0; do { $value = round ( ( $matches[1] * $convertUnit['ratio'] ), $convertUnit['round'] + $itterator ); ++$itterator; } while ( $value == 0 || $itterator == 10 ); $replacement = $value . $2 . $convertUnit['imperial'] . $4; $text = preg_replace ( $pattern, $replacement, $text, 1 ); } } return $text; } /frank 9 okt 2006 kl. 16.18 skrev Ilaria De Marinis: Hi Frank, I think preg_replace_callback is a good solution for you. If you don't want to use it, you can construct two arrays defining matches and replacements. For example: $matches [230] [120] [340] $replacements [9.1] [replace2] [replace3] After you stored matches in $matches using regular expression like yours,/preg_match_all http://it.php.net/manual/en/function.preg- split.php/ (([[:digit:]]+|[[:digit:]]+\.[[:digit:]]+)([[:blank:]]?) (mm), $string, $matches, PREG_SET_ORDER) you can define $replacements by this way: for(int =0; icount($matches); i++){ $replacements[$i]=round((substr($matches[$i][0], 0, 3)) *0.039370079),1); //take the last part of match with no digits, I don't know if there are sure 3 digits } for(int i=0; icount($matches); i++){ preg_replace($string, $matches[$i][0], $replacement[$i].in); } hope to help you Ilaria Frank Arensmeier wrote: Hello all. Is it possible to have a user defined function for the replacement within an ereg_replace (like preg_replace_callback)? I am working on a script that converts html pages with metric data into imperial data. My script takes text strings containing one or more instances of e.g. 123 mm, 321 mm, 123 kg, 123 cm2 and so on. The script searches the string with a pattern like: ([[:digit:]]+|[[:digit:]]+\.[[:digit:]]+)([[:blank:]]?)(mm) When the script finds an instance, it stores the matches into an array - ereg ( $pattern, $textstring, $matches ) The replacement (for mm) looks like: round ( ( $matches[1] * 0.039370079 ), 1 ) . $matches[2] . in Everything is working great accept when the string contains more than one instance for example of the metric unit mm. In that case, all instances of xy mm will be replaced with the first occurrence. So, a text like: The product is 230 mm tall, 120 mm thick and 340 mm wide will output as The product is 9.1 in tall, 9.1 in thick and 9.1 in wide - because the replacement string is based / calculated on the first occurrence 230 mm. Alternatively, is there a way to limit ereg_replace to only replace one instance at a time? Hopefully I am not too confusing... regards, /frank ps. of course I have searched the manual and asked Google - no luck ds. -- De Marinis Ilaria Settore Automazione Biblioteche Phone: +3906-44486052 CASPUR - Via dei Tizii ,6b - 00185 Roma e-mail: [EMAIL PROTECTED] -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php