multiple preg_replace on the same variable - php

While delving into some old code I've stumbled upon a function which is used to clean up special characters using preg_replace very excessively. Unfortunatly there's no way to avoid this cleanup, the messed up data arrive from outside.
/* Example 1: current code */
$item = preg_replace('/' . chr(196) . '/',chr(142),$item);
$item = preg_replace('/' . chr(214) . '/',chr(153),$item);
$item = preg_replace('/' . chr(220) . '/',chr(154),$item);
Alot of those lines are in there, and all do the same (using different characters), so there should be a better way to do this. My first iteration to optimize this would be to use an indexed array, like this:
/* Example 2: slightly optimized code */
$patterns = array();
$patterns[0] = '/'.chr(196).'/';
$patterns[1] = '/'.chr(214).'/';
$patterns[2] = '/'.chr(220).'/';
$reps = array();
$reps[0] = chr(142);
$reps[1] = chr(153);
$reps[2] = chr(154);
$item = preg_replace($patterns,$reps,$item);
It does the job, but I guess there's somewhere a better and/or faster way of doing this alot easier and smarter - maybe even without preg_replace. Due to the early morning and/or the lack of good coffee, I was unable to find it myself so far.
Any suggestions?

As far as you're concerned to replace characters, you can make use of strtrDocs which has a nice array parameter:
$map = array(
chr(196) => chr(142),
chr(214) => chr(153),
chr(220) => chr(154),
);
$item = strtr($item, $map);

I think you could use str_replace for this use. Not sure about the characters you're replacing tho. But if str_replace works, it'll be a lot faster than those preg_replace.
But, does those lines slow your application too much or is it just a case of seeing something you could clean up? Because if it is, don't forget to prepare enough tests to avoid creating problems.

You should use strtr here.
$item = strtr($item, chr(196) . chr(214), chr(142) . chr(153));
http://php.net/manual/en/function.strtr.php

You need not regexp to this operation(replacing constant string to another), str_replace enough for you here. Besides, str_replace allows to replace array by array as you want

preg_replace or str_replace will both be slower than strtr which is designed for exactly this purpose.
echo strtr("This is a test","aiu","AIU");
will give
ThIs Is A test

Related

Add a text in a string PHP

I have a text.
$text='userpics/115/X3WGOC0009JA.jpg';
I want to add a letter p before X3WGOC0009JA.jpg, so my output will be
$text='userpics/115/pX3WGOC0009JA.jpg';
---^
I am new to php, so I don't really know what to try, I was hoping you could guide me in the right direction
You can explode by the slash by one way.
$exploded_text = explode('/', $text);
$new_text = $exploded_text[0] . $exploded_text[1] . 'p' . $exploded_text[2];
It's not the best way, but it will work.
Based on his question, I think all he wants to do is:
$text='userpics/115/'.'p'.'X3WGOC0009JA.jpg';
First, I would get the filename using strrpos and substr:
$text = 'userpics/115/X3WGOC0009JA.jpg';
$prepend_filename = 'p';
$last_slash_pos = strrpos($text, '/');
if ($last_slash_pos === false) throw new Exception('No slashes found');
$path = substr($text, 0, $last_slash_pos);
$filename = substr($text, $last_slash_pos + 1); // Add one to skip slash
And then you can add the p (as specified in $prepend_filename) using this:
$new_path = $path . DIRECTORY_SEPARATOR . $prepend_filename . $filename;
Have you tried just setting you variables and concatenation if you doing this a bunch.
$p = 'p';
$new = "userpics/115/" . $p . "X3WGOC0009JA.jpg";
There is a function, substr_replace(), which can insert a string at a point you want.
We combine this with strRpos() which we can use to find the first slash, LOOKING IN REVERSE:
$string = substr_replace($string, 'p', strrpos($string, '/')+1 );
This will insert 'p' in $string. At the position of the '/' in $string. The +1 corrects the 'cursor' to the character AFTER the slash.
Why not use the explode functions?
Very simple: Those are slow. String functions like strpos() and substr_replace() are VERY fast, especially on small strings.
Arrays are WAY slower in php, so don't go there unless you have to. For simple string- manipulation you should use simple string functions (sounds easy when you put it like that doesnt it?).
In a simple test I benchmarked the explode variant like user3758531's VS the string variant like mine:
100.000 tries with arrays: 1.5 sec
100.000 tries with strings: 0.9 sec
In this one situation, with this one action timing doesnt really matter. But apply this way of thinking thoughout the website and you will notice it speeding up/slowing down.

I need to get a value in PHP "preg_match_all" - Basic (I think)

I am trying to use a License PHP System…
I will like to show the status of their license to the users.
The license Server gives me this:
name=Service_Name;nextduedate=2013-02-25;status=Active
I need to have separated the data like this:
$name = “Service_Name”;
$nextduedate = “2013-02-25”;
$status = “Active”;
I have 2 days tring to resolve this problem with preg_match_all but i cant :(
This is basically a query string if you replace ; with &. You can try parse_str() like this:
$string = 'name=Service_Name;nextduedate=2013-02-25;status=Active';
parse_str(str_replace(';', '&', $string));
echo $name; // Service_Name
echo $nextduedate; // 2013-02-25
echo $status; // Active
This can rather simply be solved without regex. The use of explode() will help you.
$str = "name=Service_Name;nextduedate=2013-02-25;status=Active";
$split = explode(";", $str);
$structure = array();
foreach ($split as $element) {
$element = explode("=", $element);
$$element[0] = $element[1];
}
var_dump($name);
Though I urge you to use an array instead. Far more readable than inventing variables that didn't exist and are not explicitly declared.
It sounds like you just want to break the text down into separate lines along the semicolons, add a dollar sign at the front and then add spaces and quotes. I'm not sure you can do that in one step with a regular expression (or at least I don't want to think about what that regular expression would look like), but you can do it over multiple steps.
Use preg_split() to split the string into an array along the
semicolons.
Loop over the array.
Use str_replace to replace each '=' with ' = "'.
Use string concatenation to add a $ to the front and a "; to the end of each string.
That should work, assuming your data doesn't include quotes, equal signs, semicolons, etc. within the data. If it does, you'll have to figure out the parsing rules for that.

PHP Remove Value of String with Variable Numbers

Basically from a database I am getting data that is formatted like this nameofproject101 Now this could continue to increase so eventually it could be nameofproject1001 my question is how can I trim off the number and just get the name of the project. I thought about using substr but since I dont know the length always I cant really do that. Since the numbers differ I dont think I can use str_replace is there any way to accomplish this?
It sounds like something is way off about your database scheme. You should probably try to do refactor/normalize your scheme.
But in the meantime, you can use rtrim() to trim all numbers off of the right side.
$val = rtrim($val, '0123456789');
Examples
Input Output
nameofproject1001 nameofproject
nameofproject nameofproject
n4me0fproj3ct1001 n4me0fproj3ct
for string like, project12V123, It is better to do this
$text = `project12V123`;
$text = preg_replace('/([\w]+)([^0-9])([0-9])+$/', '$1$2', $text);
Will return:
Project12V
or use rtrim:
$text = rtrim($text,'0123456789');
You should definitely use regular expressions:
$fullname = "nameofproject101";
preg_match("/([a-z]+)([0-9]+)/i", $fullname, $matches);
$name = $matches[1];
$number = $matches[2];
echo "'$fullname' is '$name' followed by '$number'";
preg_replace('/[^a-z]/i', '', $string);

Removing comments from JS / CSS file using [PHP]

I'm building a PHP script to minify CSS/Javascript, which (obviously) involves getting rid of comments from the file. Any ideas how to do this? (Preferably, I need to get rid of /**/ and // comments)
Pattern for remove comments in JS
$pattern = '/((?:\/\*(?:[^*]|(?:\*+[^*\/]))*\*+\/)|(?:\/\/.*))/';
Pattern for remove comments in CSS
$pattern = '!/\*[^*]*\*+([^/][^*]*\*+)*/!';
$str = preg_replace($pattern, '', $str);
I hope above should help someone..
REFF : http://castlesblog.com/2010/august/14/php-javascript-css-minification
That wheel has been invented -- https://github.com/mrclay/minify.
PLEASE NOTE - the following approach will not work in all possible scenarios. Test before using in production.
Without preg patterns, without anything alike, this can be easily done with PHP built-in TOKENIZER. All three (PHP, JS and CSS as well) share the same way of representing comments in source files, and PHP's native, built-in token_get_all() function (without TOKEN_PARSE flag) can do dirty trick, even if the input string isn't well formed PHP code, which is exactly what one might need. All it asks is <?php at start of the string and magic happens. :)
<?php
function no_comments (string $tokens)
{ // Remove all block and line comments in css/js files with PHP tokenizer.
$remove = [];
$suspects = ['T_COMMENT', 'T_DOC_COMMENT'];
$iterate = token_get_all ('<?php '. PHP_EOL . $tokens);
foreach ($iterate as $token)
{
if (is_array ($token))
{
$name = token_name ($token[0]);
$chr = substr($token[1],0,1);
if (in_array ($name, $suspects)
&& $chr !== '#') $remove[] = $token[1];
}
}
return str_replace ($remove, '', $tokens);
}
The usage goes something like this:
echo no_comments ($myCSSorJsStringWithComments);
Take a look at minify, a "heavy regex-based removal of whitespace, unnecessary comments and tokens."

search string with preg_replace

$html = file_get_contents("1.html");
eval("print \"" . addcslashes(preg_replace("/(---(.+?)---)/", "\\2", $html), '"') . "\";");
This searches an string and replaces ---$variable--- with $variable.
How can I rewrite the script so that it searches for ---$_SESSION['variable']--- and replaces with $_SESSION['variable']?
You could just change the replacement to:
preg_replace("/(---\\\$_SESSION\\['(.+?)'\\]---)/", "\${\$_SESSION['\\2']}", $html)
but I wouldn't at all recommend it. As always, eval is a big clue you're doing something wrong.
Non-templating uses of $ in 1.html or the session variable will cause errors. Arbitrary code in 1.html or the session variable can be executed via the ${...} syntax, potentially compromising your server. Less-than signs or ampersands in the session variable will be output as-is, leading to cross-site-scripting attacks.
A better strategy is to keep the string as just a string, not a PHP command. Find the ---...--- sections and replace those separately:
$parts= preg_split('/---(.+?)---/', $html, null, PREG_SPLIT_DELIM_CAPTURE);
for ($i= 1; $i<count($parts); $i+= 2) {
$part= trim($parts[$i]);
if (strpos($part, "\$_SESSION['")==0) {
$key= stripcslashes(substr($part, 11, -2));
$parts[$i]= htmlspecialchars($_SESSION[$key], ENT_QUOTES);
}
}
$html= implode('', $parts);
(Not tested, but should be along the right lines. You may not want htmlspecialchars if you really want your variables to contain active HTML; this is not usually the case.)
The function you need is preg_quote(). But before I post any code here: Are you really really really sure your $html or your $_SESSION['variable'] contains no malicious strings like $(cat /etc/passwd)? If you are, double-check. If you still are, go ahead using this:
preg_replace("/(---" . preg_quote($_SESSION['variable'], '/') . "---)/", "\\2", $html)

Categories