regex replace all occurances of one character? - php

Lots of topics on this but i can't figure it out, looking for some tips, shouldn't be that difficult.
I have filename:
test_file_from_mpc.mp4_snapshot_13.29_[2015.05.13_21.10.11].jpg
i'm trying to use regex to replace the characters _ and then everything starting from snapshot
I got snapshot covered, but i can't seem to get how to catch all the occurances of _ to be selected
(_)(snapshot)(.*)
selects only 1 _
I read that . should select "any single character" not sure how to use this properly or if it is what i am looking for.
Any guidance would be great! (this is probably 100% a dupe but i have checked all the suggested threads without finding the solution to this seemingly easy problem!)

Can't comment yet, but for regex to match more than one occurrence, you need the g - global modifier.
/(_snapshot.*$|_|\.)/gi
https://regex101.com/r/aI7fF8/2
If you replace purely with space all matching occurences, remember to trim last space.
Here's a php sample as well
<?php
$str = "test_file_from_mpc.mp4_snapshot_13.29_[2015.05.13_21.10.11].jpg";
$res = preg_replace(array("/_snapshot.*$/", "/[_.]/"), array("", " "), $str);
print $res; // test file from mpc mp4

snapshot.*$|[_.]
You can try this.Replace by space.See demo.
https://regex101.com/r/mT0iE7/13
$re = "/snapshot.*$|[_.]/im";
$str = "test_file_from_mpc.mp4_snapshot_13.29_[2015.05.13_21.10.11].jpg";
$subst = " ";
$result = preg_replace($re, $subst, $str);

Another (potentially faster, but not prettier) way would be to use explode() & implode().
// Split string by underscores
$pieces = explode('_', $filename);
// Get the number of pieces
$n = count($pieces);
// Keep just the file extension in the last piece
$pieces[$n] = substr($pieces[$n], strpos($pieces[$n], '.'));
// Remove the other unwanted pieces
unset($pieces[$n - 1];
unset($pieces[$n - 2];
// Reassemble with spaces instead of underscores
$new_string = implode(' ', $pieces);

Related

Remove s or 's from all words in a string with PHP

I have a string in PHP
$string = "Dogs are Jonny's favorite pet";
I want to use regex or some method to remove s or 's from the end of all words in the string.
The desired output would be:
$revisedString = "Dog are Jonny favorite pet";
Here is my current approach:
<?php
$string = "Dogs are Jonny's favorite pet";
$stringWords = explode(" ", $string);
$counter = 0;
foreach($stringWords as $string) {
if(substr($string, -1) == s){
$stringWords[$counter] = trim($string, "s");
}
if(strpos($string, "'s") !== false){
$stringWords[$counter] = trim($string, "'s");
}
$counter = $counter + 1;
}
print_r($stringWords);
$newString = "";
foreach($stringWords as $string){
$newString = $newString . $string . " ";
}
echo $newString;
}
?>
How would this be achieved with REGEX?
For general use, you must leverage much more sophisticated technique than an English-ignorant regex pattern. There may be fringe cases where the following pattern fails by removing an s that it shouldn't. It could be a name, an acronym, or something else.
As an unreliable solution, you can optionally match an apostrophe then match a literal s if it is not immediately preceded by another s. Adding a word boundary (\b) on the end improves the accuracy that you are matching the end of words.
Code: (Demo)
$string = "The bass can access the river's delta from the ocean. The fishermen, assassins, and their friends are happy on the banks";
var_export(preg_replace("~'?(?<!s)s\b~", '', $string));
Output:
'The bass can access the river delta from the ocean. The fishermen, assassin, and their friend are happy on the bank'
PHP Live Regex always helped me a lot in such moments. Even already knowing how REGEX works, I still use it just to be sure some times.
To make use of REGEX in your case, you can use preg_replace().
<?php
// Your string.
$string = "Dogs are Jonny's favorite pet";
// The vertical bar means "or" and the backslash
// before the apostrophe is needed so you don't end
// your pattern string since we're using single quotes
// to delimit it. "\s" means a single space.
$regex_pattern = '/\'s\s|s\s|s$/';
// Fill the preg_replace() with the pattern, the replacement
// (a single space in this case), your string, -1 (so preg_replace()
// will replace all the matches) and a variable of your desire
// to be the "counter" (preg_replace() will automatically
// fill it).
$newString = preg_replace($regex_pattern, ' ', $string, -1, $counter);
// Use the rtrim() to remove spaces at the right of the sentence.
$newString = rtrim($newString, " ");
echo "New string: " . $newString . ". ";
echo "Replacements: " . $counter . ".";
?>
In this case, the function will identify any "'s" or "s" with spaces (\s) after them and then replace them with a single space.
The preg_replace() will also count all the replacements and register them automatically on $counter or any variable you place there instead.
Edit:
Phil's comment is right and indeed my previous REGEX would lose a "s" at the end of the string. Adding "|s$" will solve it. Again, "|" means "or" and the "$" means that the "s" must be at the end of the string.
In attention to mickmackusa's comment, my solution is meant only to remove "s" characters at the end of words inside the string as this was Sparky Johnson' request here. Removing plurals would require a complex code since not only we need to remove "s" characters from plural only words but also change verbs and other stuff.

How can remove the numberic suffix in php?

For example, if I want to get rid of the repeating numeric suffix from the end of an expression like this:
some_text_here_1
Or like this:
some_text_here_1_5
and I want finally receive something like this:
some_text_here
What's the best and flexible solution?
$newString = preg_replace("/_?\d+$/","",$oldString);
It is using regex to match an optional underscore (_?) followed by one or more digits (\d+), but only if they are the last characters in the string ($) and replacing them with the empty string.
To capture unlimited _ numbers, just wrap the whole regex (except the $) in a capture group and put a + after it:
$newString = preg_replace("/(_?\d+)+$/","",$oldString);
If you only want to remove a numberic suffix if it is after an underscore (e.g. you want some_text_here14 to not be changed, but some_text_here_14 to be changed), then it should be:
$newString = preg_replace("/(_\d+)+$/","",$oldString);
Updated to fix more than one suffix
Strrpos is far better than regex on such a simple string problem.
$str = "some_text_here_13_15";
While(is_numeric(substr($str, strrpos($str, "_")+1))){
$str = substr($str,0 , strrpos($str, "_"));
}
Echo $str;
Strrpos finds the last "_" in str and if it's numeric remove it.
https://3v4l.org/OTdb9
Just to give you an idea of what I mean with regex not being a good solution on this here is the performance.
Regex:
https://3v4l.org/Tu8o2/perf#output
0.027 seconds for 100 runs.
My code with added numeric check:
https://3v4l.org/dkAqA/perf#output
0.003 seconds for 100 runs.
This new code performs even better than before oddly enough, regex is very slow. Trust me on that
You be the judge on what is best.
First you'll want to do a preg_replace() in order to remove all digits by using the regex /\d+/. Then you'll also want to trim any underscores from the right using rtrim(), providing _ as the second parameter.
I've combined the two in the following example:
$string = "some_text_here_1";
echo rtrim(preg_replace('/\d+/', '', $string), '_'); // some_text_here
I've also created an example of this at 3v4l here.
Hope this helps! :)
$reg = '#_\d+$#';
$replace = '';
echo preg_replace($reg, $replace, $string);
This would do
abc_def_ghi_123 > abc_def_ghi
abc_def_1 > abc_def
abc_def_ghi > abc_def_ghi
abd_def_ > abc_def_
abc_123_def > abd_123_def
in case of abd_def_123_345 > abc_def
one could change the line
$reg = '#(?:_\d+)+$#';

PHP str_replace can't give me the output I want

I want to replace a string at a particular position. For that I used str_replace() PHP function, but after that, I can't get an output. Here I show you what I want.
$str = "hello 8-7-2015 world -12";
// here I want replace - with ' desh ' but in date only. That I have detected using check before character if space than it should be 'minus' otherwise it should be 'desh'.
$key = strpos($str, "-");
if($key !== false){
$a = substr($str, $key-1 , 1);
if($a != " "){
$str = str_replace("-","desh",$str);
}else{
$str = str_replace("-","minus",$str);
}
}
I get output like: hello 8 desh 7 desh 2015 world desh 12 . Everywhere there is desh I want minus 12. Other values are okay and should not be changed.
Means particular position change.
Your code (with an if) doesn't loop over the string looking for all occurrences, so that should have raised an alert flag with you when all the occurrences were changed.
What it does is to find the first occurrence, which isn't preceded by a space, then it executes:
str_replace("-","desh",$str);
which replaces all occurrences within the string. In order to do what you want, all you need is:
str_replace(" -"," minus",$str);
str_replace("-","desh",$str);
This will first take care of all - character preceded by a space, turning them into " minus".
The second line will then take care of all the remaining - characters, replacing them with "desh".
Just as an aside, if you're doing this to be able to "speak" the words (in the sense of a text-to-speech (TTS) program), you probably want spaces on either sides of the words you're adding. You can achieve that with a very small modification:
str_replace(" -"," minus ",$str);
str_replace("-"," desh ",$str);
That may make it easier for your TTS code to handle the words.
There's no point in your condition since str_replace takes effect on whole the string without any relation to your $key variable.
$str = str_replace(" -","minus",$str);
$str = str_replace("-","desh",$str);
Truth is that you don't even need that condition. Simply use the first str_replace when the search term has blank space prior to it and the second str_replce doesn't. (order it's important).
You can use regex:
$str = preg_replace(
['/(\d{1,2})-(\d{1,2})-(\d{2,4})/','/-(\d+)/'],
['$1 desh $2 desh $3', 'minus $1'],
$str);
check this,
First you have to get the date from the string, then change the date format as you want after that concatenate with other strings
$str = explode(' ',$str);
$str1 = str_replace("-","desh",$str[1]);
$str2 = str_replace("-","minus",$str[2]);
$str = $str[0].$str1.$str2;

PHP trim and return a string from its right

I'm trying to take a string that's output from MySql like this (MySql outputs X characters):
$str = 'Buddy you're a boy make a big noise Playin in the stre';
and trying to start from the right side, trim whatever is there up till the first space. Sounded simple when I got down to it, but now, it has my brain and fingers in knots.
The output I'm tying to achieve is simple:
$str = 'Buddy you're a boy make a big noise Playin in the';
Notice, that characters starting from the right, till the first space, are removed.
Can you help?
My Fiddle
$str = 'Buddy you\'re a boy make a big noise Playin in the stre';
//echo rtrim($str,' ');
It's a useful idiom to remember on its own: to remove all the characters preceding a specific one from the right side of the string (including that special character), use the following:
$trimmed = substr($str, 0, strrpos($str, ' '));
... where ' ' is that special character.
Demo
If you don't know, however, whether or not the character is present, you'd check the result of sttrrpos first:
$last_space_index = strrpos($str, ' ');
$trimmed = $last_space_index !== false
? substr($str, 0, $last_space_index)
: $str;
And if there can be more than one character that you need to trim, like in 'hello there test' line, just rtrim the result:
$trimmed = rtrim(substr($str, 0, strrpos($str, ' ')), ' ');
In this case, however, a regex-based solution looks more appropriate:
$trimmed = preg_replace('/ +[^ ]*$/', '', $str);
I think your best option would be a regex replace:
preg_replace('/\s+\S*$/', '', $str);
which outputs Buddy you're a boy make a big noise Playin in the
And the Fiddle
it's probably easier to do it with regex, but I'm sooo bad with that! You shoud try this:
// Get all the words in an array
$strArray = explode(" ", $str);
// Remove the last word.
array_pop($strArray);
// Get it back into a sentence
$newString = implode(" ", $strArray);
There's a hundred ways to do this, here are some options:
array_pop'ing the last word off an array we create from explode:
$arr = explode(" ", $str);
$fixed_arr = array_pop($arr);
$result = implode(" ", $arr);
Using regular expressions:
$result = preg_replace('/\s+\S*$/', '', $str);
and using strrpos and substr:
$spacePos = strrpos($str, ' ');
$result = substr($str, 0, $spacePos);
In mysql use
left(field,length)
to output only the strlen first digits
right(field,length) having opposite effects
otherwise use substr($string,0,$length) or regex in php
As a matter of regex performance comparison, the regex engine can move faster through the string when it can perform greedy matching with minimal backtracking.
/ +[^ ]*$/ uses 68 steps. (#raina77ow)
/(?:[^ ]+\K )+.*/ uses 56 steps. (#mickmackusa)
/(?:\K [^ ]*)+/ uses 48 steps. (#mickmackusa)
\s+\S*$ uses 34 steps. (#ChrisBornhoft and #RyanKempt)
/.*\K .*/ uses just 15 steps. (#mickmackusa)
Based on these comparisons, I recommend greedily matching any characters, then restarting the fullstring match before matching the last occurring space, then matching zero or more characters until the end of the string.
Code: (Demo)
$string = "Buddy you're a boy make a big noise Playin in the stre";
var_export(
preg_replace('/.*\K .*/', '', $string)
);
Output:
'Buddy you\'re a boy make a big noise Playin in the'

Using preg_replace to modify first space, but not inside a group of words using PHP

I would like to replace commas and potential spaces (i.e. that user can type or not) of an expression using preg_replace.
$expression = 'alfa,beta, gamma gmm, delta dlt, epsilon psln';
but I was unable to format the output as I want:
'alfa|beta|gamma gmm|delta dlt|epsilon psln'
Amongst others I tried this:
preg_replace (/,\s+/, '|', $expression);
and although it was the closest I got, it's not yet right. With code above I receive:
alfa,beta|gamm|gmm|delt|dlt|epsilo|psl|
Then I tried this (with | = OR):
preg_replace (/,\s+|,/, '|', $expression);
and although I solved the problem with the comma, it is still wrong:
alfa|beta|gamm|gmm|delt|dlt|epsilo|psl|
What should I do to only delete space after comma and not inside the word-group?
Many thanks in advance!
Use ,\s* instead of ,\s+ and replace the matched characters with | symbol. If you use ,\s+, it matches the commas and the following one or more spaces but it forgot the commas which are alone. By making the occurrence of spaces to zero or more times, it would also match the commas which are alone.
DEMO
Code:
<?php
$string = 'alfa,beta, gamma gmm, delta dlt, epsilon psln';
$pattern = "~,\s*~";
$replacement = "|";
echo preg_replace($pattern, $replacement, $string);
?>
Output:
alfa|beta|gamma gmm|delta dlt|epsilon psln
How about using regular PHP functions to achieve this?
<?php
$expression = 'alfa,beta, gamma gmm, delta dlt, epsilon psln';
$pieces = explode(',', $expression);
foreach($pieces as $k => $v)
$pieces[$k] = trim($v);
$result = implode('|', $pieces);
echo $result;
?>
Output:
alfa|beta|gamma gmm|delta dlt|epsilon psln
This will distinguish between spaces at start/end of piece and spaces in pieces.

Categories