PHP Replace Leading Zeros with Same Number of Spaces - php

I'd like to replace a string like 0001 with " 1" with 3 spaces.
I've tried str_replace but that doesn't work on 0010.
I've tried some preg_replace but can't get the replacement right to replace the same number
I've written this basic thing and it works, but am looking for something more efficient if possible.
$pin = '0010';
$temp = ltrim($pin, '0');
$spaces = strlen($pin) - strlen($temp);
for ($x=1;$x<=$spaces;$x++) $temp = ' '.$temp;
echo $temp;
Closest I got with preg_replace was this but I'm not sure what to do with replacement:
preg_replace('/0+/', ' ', $pin)

\G for the win!
https://www.regular-expressions.info/continue.html
\G will match the start of the string and continue to match until it can't.
What is the use of '\G' anchor in regex?
Match a zero from the start of the string, then match every following zero one-at-a-time. Replace every matched zero with a space.
Code: (Demo)
$pin = '0010';
var_export(preg_replace('~\G0~', ' ', $pin));
Output:
' 10'

I don't see how to do this any easier with a regular expression, but you could make your other code more concise by using str_repeat:
$pin = '0010';
$temp = ltrim($pin, '0');
$spaces = strlen($pin) - strlen($temp);
$new_pin = str_repeat(' ', $spaces) . $temp;
echo $new_pin;

You said:
but am looking for something more efficient if possible
First, note that a one-liner isn't necessarily efficient(as you tried for preg_replace() and regex is actually a bit slower since it gets compiled first).
Second, you can better adopt for just a 2 pass approach over the string. This also edits the string in-place without extra string variables which is desirable in your case.
Snippet:
<?php
$str = '000010';
$len = strlen($str);
for($i = 0; $i < $len; ++$i){
if($str[$i] == '0'){
$str[$i] = ' ';
}else{
break;
}
}
echo $str;

Related

Using PHP preg_replace match result in a math operation?

I want to find a number in a string, add one to it, and replace it. These don't work:
$new_version =
preg_replace("/str\/(\d+)str/", "str/".("$1"+1)."str", $original);
$new_version =
preg_replace("/str\/(\d+)str/", "str/".(intval("$1")+1)."str", $original);
Where 'str' is a very identifiable string, each side of the number (and does not contain numbers).
I realise I can do this in more than one line of code quite easily but it seems like this should be possible.
Using a callback function allows you to cast a match to number and increment, e.g.:
preg_replace_callback(
"/str\/(\d+)str/",
function($matches) { return "str/" . ((int)$matches[1] + 1) . "str"; },
$original
);
Solely using str_replace you can get the number from the string, add one to it, and the replace the old number with the new one :
$str = 'In My Cart : 11 items';
$nb = preg_replace('/\D/', '', $str);
$nb += 1;
$str = str_replace($nb-1, $nb, $str);
echo $str;

Formatting string according to pattern without regex in php

How can I format an arbitrary string according to a flexible pattern? The only solution I came up with is using regular expressions, but then I need 2 "patterns" (one for the search and one for the output).
Example:
$str = '123ABC5678";
Desired output: 12.3AB-C5-67.8
I would like to use a pattern in a variable (one that a user can easily define without knowledge of regular expressions) It could look like this:
$pattern = '%%.%%%-%%-%%.%';
So the user would just have to use 2 different characters (% and .)
A solution with regex would look like this:
$str = '123ABC5678';
$pattern_src = '#(.{2})(.{3})(.{2})(.{2})(.{1})#';
$pattern_rpl = "$1.$2-$3-$4.$5";
$res = preg_replace($pattern_src, $pattern_rpl, $str);
//$res eq 12.3AB-C5-67.8
Way too complicated since the user would need to define $pattern_src and $pattern_rpl. If the string could vary in length, it would be even more complex to explain.
Yes, I could write a function/parser that builds the required regular expressions based on a simple user pattern like %%.%%%-%%-%%.%. But I wonder if there is any "built in" way to achieve this with php? I was thinking about sprintf etc., but that doesn't seem to do the trick. Any ideas?
I was thinking about sprintf etc., but that doesn't seem to do the trick.
You're on the right track. You can accomplish this with vsprintf as follows:
$str = '123ABC5678';
$pattern = '%%.%%%-%%-%%.%';
echo vsprintf(str_replace('%', '%s', $pattern), str_split($str));
Output:
12.3AB-C5-67.8
This is assuming the number of % characters in $pattern match the length of $str.
Why not write a simple parser that works as follows:
For each character of pattern:
if you match percent character, output next character from input
if you match any other character, output it
$str = '123ABC5678';
$pattern = '%%.%%%-%%-%%.%';
if (strlen($str) < substr_count($pattern, '%'))
Die('The length of input string is lower than number number of placeholders');
$len = strlen($pattern);
$stringIndex = 0;
$output = '';
for ($i = 0; $i < $len; $i++) {
if ($pattern[$i] === '%') {
$output .= $str[$stringIndex];
$stringIndex++;
} else {
$output .= $pattern[$i];
}
}
echo $output;
I have a similar solution that looks like this.
<?php
$format = '%%.%%%-%%-%%.%';
$string = '123ABC5678';
$new_string = '';
$c = 0;
for( $i = 0; $i < strlen( $format ); $i++ )
{
if( $format[ $i ] == '%' )
{
$new_string .= $string[ $c ];
$c++;
}
else
{
$new_string .= $format[ $i ];
}
}
echo $new_string;
Output:
12.3AB-C5-67.8
How about this pattern from the user?
2.3-2-2.1
Where the pattern is a number means n chars, a dot or dash means add a dot or dash.
Now you make a regex to parse the user input:
preg_match_all("/(.)/", $User_input, $pattern);
Now you will have an array with either numbers or dots and dashes.
So loop through the array and build the string:
$string = '123ABC5678';
$User_input = "2.3-2-2.1";
preg_match_all("/(.)/", $User_input, $pattern);
$i=0;
$str="";
foreach($pattern[1] as $val){
if(is_numeric($val)){
$str .= substr($string,$i,$val);
$i=$i+$val;
}else{
$str .= $val;
}
}
echo $str;
https://3v4l.org/5eg5G

Formating a specific input number to another format

I need to format the following number 0825632332 to this format +27 (0)82 563 2332.
Which combination of functions would work the best, should I use regular expressions or normal string functions to perform the re-formatting? And how?
I think using a regexp is the best way, maybe something like this :
$text = preg_replace('/([0-9])([0-9]{2})([0-9]{3})([0-9]{4})/', '+27 ($1) $2 $3 $4', $num);
Be aware that $num must be a string since your number starts with 0.
You can also use character class :
$text = preg_replace('/(\d)(\d{2})(\d{3})(\d{4})/', '+27 ($1) $2 $3 $4', $num);
Since you asked - non regex solution:
<?php
function phnum($s, $format = '+27 (.).. ... ....') {
$si = 0;
for ($i = 0; $i < strlen($format); $i++)
if ($format[$i] == '.')
$output[] = $s[$si++];
else
$output[] = $format[$i];
return join('',$output);
}
echo phnum('0825632332');
?>
Regex will work nicely, replace
(\d)(\d{2})(\d{3})(\d{4})
by
+27 (\1)\2 \3 \4
You can also perform string submatching if you want.

Unable to find tokens in string

I am trying to write a small php
application and i am facing a problem.
This is suppose to get text like :
this is *noun but it is *name.
And
should take the words that start with
a star and add them to the string
tokens. However this is not working.
// get list of fields (each should have words delimited by underscores
$storyArray = split(' ', $story);
$tokens = ""; // space-delimited list of fields
for ($i = 0; $i < count($storyArray); $i++) {
if ($storyArray[$i][0] == '*')
$tokens .= $storyArray[$i] + " ";
}
$tokensArray = split(' ', $tokens);
Wow, I can't believe I've been debugging this and missing the obvious fault!
This line here:
$tokens .= $storyArray[$i] + " ";
You must concatenate with a period (.), not a plus sign! What you have right now is basically the same as $tokens .= 0;
This worked for me:
$story = "this is *noun but it is *name";
$storyArray = split(' ', $story);
$tokens = array();
for ($i = 0; $i < count($storyArray); $i++) {
if ($storyArray[$i][0] == '*') {
array_push($tokens, substr($storyArray[$i], 1));
}
}
var_dump($tokens);
$tokenString = implode(" ", $tokens);
Note that I'm pushing the tokens directly into an array, then imploding it.
"+" is for addition, not string concatenation. It casts its arguments as numbers, which will always be 0 in your source.
On another note, splitting $tokens is unnecessary. Instead, append tokens to $tokensArray:
$story = "this is *noun but it is *name";
// get list of fields (each should have words delimited by underscores
$storyArray = split(' ', $story);
$tokens = ""; // space-delimited list of fields
$tokensArray=array();
for ($i = 0; $i < count($storyArray); $i++) {
if ($storyArray[$i][0] == '*') {
$tokens .= $storyArray[$i] . " ";
$tokensArray[] = $storyArray[$i];
}
}
If you only needed $tokens for generating $tokensArray, you can get rid of it. Also, depending on whether you need $storyArray, preg_match_all(...) might be able to replace your code:
preg_match_all('/\*\w+/', $story, $tokensArray);
$tokensArray = $tokensArray[0];
You can also use a regular expression to achieve the same effect, without all the string manipulation you are doing right now. This would be the most elegant solution:
$string = "this is *noun but it is *name";
// Lets set up an empty array
$tokens = array();
preg_match_all('/\*\w+/m', $string, $tokens);
$tokens = $tokens[0]; // Only one sub-pattern, dropping unnecessary dimension.
var_dump($tokens);
Regular expressions exists to do mainly exactly the kind of task you are trying to achieve now. They are usually faster than doing string manipulations manually (Regular Expression engine in PHP is compiled code).
To explain my regex:
/: start boundary
\*: an asterisk (*)
\w: any alpha-numeric character or underscore
+: previous marker, 1 or more times. (match \w one or more times)
/: end boundary
m: multiline modifier
Replace
$tokens .= $storyArray[$i] + " ";
with
$tokens .= $storyArray[$i]." ";
And
$tokensArray = split(' ', $tokens);
with
$tokensArray = split(' ', rtrim($tokens));
$tokens .= $storyArray[$i] + " ";
in this line, you should be using the . operator to concatenate strings.

Bold the first two words from a sentence

In PHP, how can I bold the first two words from a sentence?
Thank you!
Actually, using the "limit" parameter in the function explode (3rd parameter, optional, check the function spec) you can skip the loop and make your code much simpler:
$words_array = explode(" ",$sentence,3);
$new_sencence = ( count($words_array)>2 )?
"<strong>".$words_array[0]." ".$words_array[1]."</strong> ".$words_array[2] :
"<strong>".$sentence."</strong>"; //sentence is 2 words or less, just bold it
EDIT: took care of sentences with 2 words or less
preg_replace('/^(\S+(\s+\S+)?)/', '<b>$1</b>', $sentence)
You need to break things down into steps...
1) You have a sentence, like this:
$Sentence = "Hello everybody in the world.";
2) You need to get the first two words. There are two options. You can either split the sentence on every space, or you can find the position of the second space. We'll use the first option for now...
$Words = explode(" ", $Sentence);
3) We re-assemble it all, inserting a bit of HTML to make things bold...
$WordCount = count($Words);
$NewSentence = '';
for ($i = 0; $i < $WordCount; ++$i) {
if ($i < 2) {
$NewSentence .= '<strong>' . $Words[$i] . '</strong> ';
} else {
$NewSentence .= $Words[$i] . ' ';
}
}
echo $NewSentence;

Categories