I have a string as follows...
$myString = "2,4,5,8,9,11,Inventory2,Inventory3,Inventory4,Inventory5"
I want to search for anything with the prefix "Inventory" and replace with a number which is dynamically generated. As an example say the number is "24 it will add 24 to 2 making the first matching result 26.
The end result should turn the string to "2,4,5,8,9,11,26,27,28,29"
I know how to search and replace inventory however I am unable to figure out how to add to the trailing number. Thoughts?
$str = "$comma_separated";
$expression = 'Inventory(\*),';
$replace = '24';
$newStr = str_replace("Inventory","24","$comma_separated");
I am using a static number for testing purposes
preg_replace_callback can do it:
$v = 24;
$myString = "2,4,5,8,9,11,Inventory2,Inventory3,Inventory4,Inventory5";
echo preg_replace_callback(
'/Inventory(\d+)/',
function ($m) use ($v) {
return $v + $m[1];
},
$myString
);
Related
I have a long string like below:
$string = "age1:32,age2:25,age3:52,..."
Now I want to extract the age numbers in this string and then add the numbers together and determine the average age.
I was able to extract the numbers with the help of the following code
$numbers = preg_replace('/[^0-9]/', '', $string );
but the output I get is like this and I cannot add the numbers together.
output:
322552
Using preg_match_all to find all age values followed by array_sum to find the total/average we can try:
$string = "age1:32,age2:25,age3:52,...";
preg_match_all("/age\d+:(\d+)/", $string, $matches);
print_r(array_sum($matches[1]) / count($matches[1])); // 36.333333333333
Restart the fullstring match after each colon, then match one or more digits.
preg_match_all() returns the number of matches ($count).
Divide the sum of the matches by the number of matches.
Code: (Demo)
$string = "age1:32,age2:25,age3:52,...";
$count = preg_match_all('/:\K\d+/', $string, $m);
echo array_sum($m[0] ?? []) / $count;
// 36.333333333333
If you wanted to grab all numbers, just use \d+. (Demo)
$string = "available12available15available22available11...";
$count = preg_match_all('/\d+/', $string, $m);
echo array_sum($m[0] ?? []) / $count;
how to highlight last 3 number in the string:
ab9c5lek94ke72koe8nsk9
i want output:
ab9c5lek94ke72koe8nsk9
i tried following:
$str = "ab9c5lek94ke72koe8nsk9";
$numbers = preg_replace('/[^0-9]/', '', $str );
$last3 = substr($numbers, -3);
$highlights = str_split($last3);
$output = preg_replace('/'.implode('|', $highlights).'/i', '<b>$0</b>', $str);
but it highlight:
ab9c5lek94ke72koe8nsk9
You can achieve that easily using regular expression with PHP's preg_replace() function. Just find last 3 digits 3 times at the end of the string. See the following code:
$str1 = 'ab9c5lek94ke2koe8nsk9';
$str2 = 'dag2vue41a89au76zhz30';
echo preg_replace('/(\d)([^\d]*)(\d)([^\d]*)(\d)([^\d]*)$/mui', '<b>$1</b>$2<b>$3</b>$4<b>$5</b>$6', $str1);
echo preg_replace('/(\d)([^\d]*)(\d)([^\d]*)(\d)([^\d]*)$/mui', '<b>$1</b>$2<b>$3</b>$4<b>$5</b>$6', $str2);
Outputs
ab9c5lek94ke2koe8nsk9
and
dag2vue41a89au76zhz30
You can have a regex like below:
/(\d)([^\d]*)(\d)([^\d]*)(\d)([^\d]*)$/
which is basically (\d)([^\d]*) 3 times with a $ sign at the end. It means we are matching a digit followed by 0 or more non digit characters. Note that we do need the $ sign at the end to match only last 3 digits.
Snippet:
<?php
$str = "ab9c5lek94ke2koe8nsk9";
echo preg_replace('/(\d)([^\d]*)(\d)([^\d]*)(\d)([^\d]*)$/',"<b>$1</b>$2<b>$3</b>$4<b>$5</b>$6",$str);
Demo: https://3v4l.org/PoYCG
The replacement string is just having the bold tags with group number of the matched strings which are to be highlighted.
You can split the string on the 3rd from last number, then highlight everything in that sub string and then recombine the substrings.
In my example, I get all of the numbers in the string and put them in array. Then I use that array to get the delimiter (72 in your example), then use that to split the string into two arrays, at that point you can highlight everything in array[1] and then combine it back into array[0]
$str = "ab9c5lek94ke72koe8nsk9";
// get all of the numbers in order and place into it's own array
$numbers = trim(preg_replace('/[^0-9]/', ' ', $str ));
$numbers = preg_split('/\s+/', $numbers);
// using that get the delimiter to where to split the string. and split.
$delim = $numbers[count($numbers)-3];
$arr = explode($delim, $str);
$arr[1] = $delim . $arr[1];
// then highlight everything in $arr[1]
// then combine $arr[0] and $arr[1]
Is it possible to skip a strpos/strrpos position?
$string = "This is a cookie 'cookie'.";
$finder = "cookie";
$replacement = "monster";
if (strrpos($string, $finder) !== false)
str_replace($finder, $replacement, $string);
I want to skip the 'cookie' and replace the plain cookie so it'll result in "This is a monster 'cookie'."
I don't have qualms with it finding 'cookie' first and then checking it (Obviously necessary to determine it shouldn't be replaced), but I want to make sure that while 'cookie' is still there, I can use the same function to find the unquoted cookie.
Alternatively, is there a function I haven't found yet (Through hours of searching) to get all indices of a particular word so I can check them all through a loop without the use of regex?
It's important that it's the index, not the word itself, as there are other checks that have to be done based on where in the string the word's located.
You can try a regex instead:
Try the following:
$string = "This is a cookie 'cookie'.";
var_dump(preg_replace("/(?<!')(cookie)/", ' monster', $string));
This uses preg_replace instead of str_replace to replace the string.
Edit: You can use preg_match to get the position of the matched regex in the string like:
$string = "This is a cookie 'cookie'.";
$finder = "cookie";
preg_match("/(?<!')(" . preg_quote($finder) . ")/", $string, $matches, PREG_OFFSET_CAPTURE);
var_dump($matches);
And you can use preg_quote to make sure that preg_match and preg_replace doesn't treat the $finder var as a regex. And the difference in performance is very subtle between preg and other string functions in php. You can run some benchmarks to see how it varies in your case.
The following gives the required replacement as well as the position of the replaced word.
$string = "This is a cookie 'cookie'.";
$finder = "cookie";
$replacement = "monster";
$p = -1; // helps get position of current word
$position = -1; // the position of the word replaced
$arr = explode(' ',$string);
for($i = 0; $i < count($arr); $i += 1){
// Find the position $p of each word and
// Catch $position when a replacement is made
if($i == 0){$p = 0;} else { $w =$arr[$i - 1]; $p += strlen($w) + 1;}
if($arr[$i] == $finder){ if($position < 0){$position = $p;}$arr[$i] = $replacement;}}
$newstring = implode(' ', $arr);
echo $newstring; // gives: This is a monster 'cookie'
echo '<br/>';
echo $position; // gives 10, the position of replaced element.
For the position, the assumption is that the sentence has only single spaces because spaces are used in the explode and implode functions. Otherwise a case of double or larger spaces would require modifications, possibly by replacing spaces with a unique character or set of characters such as #$# which would be used as the first argument of the explode and implode functions.
The code could be modified to capture more than one replacement, e.g. by capturing each replaced position in an array instead of testing for if(position < 0). This would also require to change the way $position is computed because its values are affected by the lengths of previous replacements.
We can do also like this for short-hand :
Include also previous letter to function str_replace like this :
$string = "This is a cookie 'cookie'.";
echo str_replace('a cookie','a monster',$string);
I am trying to something like this.
Hiding users except for first 3 characters.
EX)
apple -> app**
google -> goo***
abc12345 ->abc*****
I am currently using php like this:
$string = "abcd1234";
$regex = '/(?<=^(.{3}))(.*)$/';
$replacement = '*';
$changed = preg_replace($regex,$replacement,$string);
echo $changed;
and the result be like:
abc*
But I want to make a replacement to every single character except for first 3 - like:
abc*****
How should I do?
Don't use regex, use substr_replace:
$var = "abcdef";
$charToKeep = 3;
echo strlen($var) > $charToKeep ? substr_replace($var, str_repeat ( '*' , strlen($var) - $charToKeep), $charToKeep) : $var;
Keep in mind that regex are good for matching patterns in string, but there is a lot of functions already designed for string manipulation.
Will output:
abc***
Try this function. You can specify how much chars should be visible and which character should be used as mask:
$string = "abcd1234";
echo hideCharacters($string, 3, "*");
function hideCharacters($string, $visibleCharactersCount, $mask)
{
if(strlen($string) < $visibleCharactersCount)
return $string;
$part = substr($string, 0, $visibleCharactersCount);
return str_pad($part, strlen($string), $mask, STR_PAD_RIGHT);
}
Output:
abc*****
Your regex matches all symbols after the first 3, thus, you replace them with a one hard-coded *.
You can use
'~(^.{3}|(?!^)\G)\K.~'
And replace with *. See the regex demo
This regex matches the first 3 characters (with ^.{3}) or the end of the previous successful match or start of the string (with (?!^)\G), and then omits the characters matched from the match value (with \K) and matches any character but a newline with ..
See IDEONE demo
$re = '~(^.{3}|(?!^)\G)\K.~';
$strs = array("aa","apple", "google", "abc12345", "asdddd");
foreach ($strs as $s) {
$result = preg_replace($re, "*", $s);
echo $result . PHP_EOL;
}
Another possible solution is to concatenate the first three characters with a string of * repeated the correct number of times:
$text = substr($string, 0, 3).str_repeat('*', max(0, strlen($string) - 3));
The usage of max() is needed to avoid str_repeat() issue a warning when it receives a negative argument. This situation happens when the length of $string is less than 3.
I need to have the word count of the following unicode string. Using str_word_count:
$input = 'Hello, chào buổi sáng';
$count = str_word_count($input);
echo $count;
the result is
7
which is aparentley wrong.
How to get the desired result (4)?
$tags = 'Hello, chào buổi sáng';
$word = explode(' ', $tags);
echo count($word);
Here's a demo: http://codepad.org/667Cr1pQ
Here is a quick and dirty regex-based (using Unicode) word counting function:
function mb_count_words($string) {
preg_match_all('/[\pL\pN\pPd]+/u', $string, $matches);
return count($matches[0]);
}
A "word" is anything that contains one or more of:
Any alphabetic letter
Any digit
Any hyphen/dash
This would mean that the following contains 5 "words" (4 normal, 1 hyphenated):
echo mb_count_words('Hello, chào buổi sáng, chào-sáng');
Now, this function is not well suited for very large texts; though it should be able to handle most of what counts as a block of text on the internet. This is because preg_match_all needs to build and populate a big array only to throw it away once counted (it is very inefficient). A more efficient way of counting would be to go through the text character by character, identifying unicode whitespace sequences, and incrementing an auxiliary variable. It would not be that difficult, but it is tedious and takes time.
You may use this function to count unicode words in given string:
function count_unicode_words( $unicode_string ){
// First remove all the punctuation marks & digits
$unicode_string = preg_replace('/[[:punct:][:digit:]]/', '', $unicode_string);
// Now replace all the whitespaces (tabs, new lines, multiple spaces) by single space
$unicode_string = preg_replace('/[[:space:]]/', ' ', $unicode_string);
// The words are now separated by single spaces and can be splitted to an array
// I have included \n\r\t here as well, but only space will also suffice
$words_array = preg_split( "/[\n\r\t ]+/", $unicode_string, 0, PREG_SPLIT_NO_EMPTY );
// Now we can get the word count by counting array elments
return count($words_array);
}
All credits go to the author.
I'm using this code to count word. You can try this
$s = 'Hello, chào buổi sáng';
$s1 = array_map('trim', explode(' ', $s));
$s2 = array_filter($s1, function($value) { return $value !== ''; });
echo count($s2);