php regex replace each character with asterisk - php

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.

Related

PHP wrapping last two letters of string with HTML

I am running into a problem trying to do a replacement on a few strings. Essentially what I have is a bunch of prices on my page that look like
RMB148.00
What i am trying to do is run a replace on only the last 2 numbers so i can do something like
RMB14800
Preg replace works fine for the RMB part because it is always there.
My problem is the last two numbers can be anything it all depends on the price so I cant just remove and replace, I need to just wrap HTML <sup> tags around them.
$string = $product['price'];
$string = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $string);
echo preg_replace('/RMB/', '<sup class="currency-sym">RMB</sup>', $string, 1);
Assuming the last two characters are digits, you could just
$string=preg_replace('/(\d\d)$/', '<sup class="currency-sym">\1</sup>', $string);
If not,
$string=preg_replace('/(..)$/', '<sup class="currency-sym">\1</sup>', $string);
should do the trick.
Alternativly use
$string=substr($string,0,-2).'<sup class="currency-sym">'.substr($string,-2).'</sup>';
Here is a regex solution that looks for the final digit notation at the end of your string.
$string = 'RMB148.00';
$string = preg_replace('/(\d+)\.(\d{2})\z/','$1<sup>$2</sup>',$string);
echo $string;
You could use the following with the explode () function
$string = explode ('.', $product['price']);
$new_string = $string[0].'<sup>'. $string [1]. '</sup>';
And do the regex for the RMB the same way.
Code.
<?php
$string = '14842.00';
$string = substr($string, 0, strlen($string) - 2) . '<sup>' . substr($string, strlen($string) - 2, 2) . '</sup>';
echo $string;
Try online sandbox.
Explanation.
substr($s, $i, $l) gets $l symbols of $s, started from $i index (indexes starts from zero).
So first substr($string, 0, strlen($string) - 2) gets all string except last two symbols.
Second substr($string, strlen($string) - 2, 2) gets only last two symbols.
More about substr.
You should use a pattern matching regex. Note the $1 in the replacement argument matches (\d{2}) in the pattern argument. preg_replace() only replaces the matched pattern. This pattern matches . followed by any two digits. Since . is not included in the replacement argument it does not show up in your $string.
$string = preg_replace('/\.(\d{2})$/', '<sup>$1</sup>', $string);
Of course, you could use one preg_replace to do what you want:
$string = preg_replace('/^(RMB)(\d+)(\.(\d{2}))?$/', "<sup class='currency-sym'>$1</sup>$2<sup>$4</sup>", $string);
The second example may be a good idea if you want DOM integrity, otherwise it creates an empty <sup></sup> when there is no decimal.

How many times "-" at beginning of string (before alphabet letter)

I'm having trouble knowing how many times that the - character is in front of my string.
Some examples:
$string = "-Lorem Ipsum"; // 1
$string = "--Lorem Ipsum"; // 2
$string = "---Lorem Ipsum"; // 3
$string = "--Lorem-Ipsum"; // 2
But how can I find this? I know you can search the number of occurrences of a character in a string. But I want the number of - characters before an alphabet letter. Not all the sequences (see last example).
How should I approach this?
You can use the old school trick of using a string as an array here as such:
$search="-";
$i=0;
while($string[$i]==$search)
{
$i++;
}
echo "Found $i instances at the start of the string.";
What about using ltrim() and strlen()
echo strlen($string) - strlen(ltrim($string, "-"));
See example at eval.in
it would also work -
preg_match('/(?!-)/', $string, $match, PREG_OFFSET_CAPTURE);
$match - the position of any character but - which is indeed the count of -.

Replace only at the end of the string

echo $string can give any text.
How do I remove word "blank", only if it is the last word of the $string?
So, if we have a sentence like "Steve Blank is here" - nothing should not removed, otherwise if the sentence is "his name is Granblank", then "Blank" word should be removed.
You can easily do it using a regex. The \b ensures it's only removed if it's a separate word.
$str = preg_replace('/\bblank$/', '', $str);
As a variation on Teez's answer:
/**
* A slightly more readable, non-regex solution.
*/
function remove_if_trailing($haystack, $needle)
{
// The length of the needle as a negative number is where it would appear in the haystack
$needle_position = strlen($needle) * -1;
// If the last N letters match $needle
if (substr($haystack, $needle_position) == $needle) {
// Then remove the last N letters from the string
$haystack = substr($haystack, 0, $needle_position);
}
return $haystack;
}
echo remove_if_trailing("Steve Blank is here", 'blank'); // OUTPUTS: Steve blank is here
echo remove_if_trailing("his name is Granblank", 'blank'); // OUTPUTS: his name is Gran
Try the below code:
$str = trim($str);
$strlength = strlen($str);
if (strcasecmp(substr($str, ($strlength-5), $strlength), 'blank') == 0)
echo $str = substr($str, 0, ($strlength-5))
Don't use preg_match unless it is not required. PHP itself recommends using string functions over regex functions when the match is straightforward. From the preg_match manual page.
ThiefMaster is quite correct. A technique that doesn't involve the end of line $ regex character would be to use rtrim.
$trimmed = rtrim($str, "blank");
var_dump($trimmed);
^ That's if you want to remove the last characters of the string. If you want to remove the last word:
$trimmed = rtrim($str, "\sblank");
var_dump($trimmed);

How to replace the Last "s" with "" in PHP

I need to know how I can replace the last "s" from a string with ""
Let's say I have a string like testers and the output should be tester.
It should just replace the last "s" and not every "s" in a string
how can I do that in PHP?
if (substr($str, -1) == 's')
{
$str = substr($str, 0, -1);
}
Update: Ok it is also possible without regular expressions using strrpos ans substr_replace:
$str = "A sentence with 'Testers' in it";
echo substr_replace($str,'', strrpos($str, 's'), 1);
// Ouputs: A sentence with 'Tester' in it
strrpos returns the index of the last occurrence of a string and substr_replace replaces a string starting from a certain position.
(Which is the same as Gordon proposed as I just noticed.)
All answers so far remove the last character of a word. However if you really want to replace the last occurrence of a character, you can use preg_replace with a negative lookahead:
$s = "A sentence with 'Testers' in it";
echo preg_replace("%s(?!.*s.*)%", "", $string );
// Ouputs: A sentence with 'Tester' in it
$result = rtrim($str, 's');
$result = str_pad($result, strlen($str) - 1, 's');
See rtrim()
Your question is somewhat unclear whether you want to remove the s from the end of the string or the last occurence of s in the string. It's a difference. If you want the first, use the solution offered by zerkms.
This function removes the last occurence of $char from $string, regardless of it's position in the string or returns the whole string, when $char does not occur in the string.
function removeLastOccurenceOfChar($char, $string)
{
if( ($pos = strrpos($string, $char)) !== FALSE) {
return substr_replace($string, '', $pos, 1);
}
return $string;
}
echo removeLastOccurenceOfChar('s', "the world's greatest");
// gives "the world's greatet"
If your intention is to inflect, e.g singularize/pluralize words, then have a look at this simple inflector class to know which route to take.
$str = preg_replace("/s$/i","",rtrim($str));
The very simplest solution is using rtrim()
That is exactly what that function is intended to be used for:
Strip whitespace (or other characters) from the end of a string.
Nothing simpler than that, I am not sure why, and would not follow the suggestions in this thread going from regex to "if/else" blocks.
This is your code:
$string = "Testers";
$stripped = rtrim( $string, 's' );
The output will be:
Tester

Replace all certain character except first occurrence in PHP

Example
Input = 1.1.0.1
Expected output = 1.101
You could make use substr() and str_replace() fairly easily:
$str = '1.1.0.1';
$pos = strpos($str,'.');
if ($pos !== false) {
$str = substr($str,0,$pos+1) . str_replace('.','',substr($str,$pos+1));
}
echo $str;
$s = preg_replace('/((?<=\.)[^.]*)\./', '$1', $s);
Matches zero or more non-dot characters followed by a dot, but only if the match was preceded by a dot. This prevents a match on the initial digit(s). Replaces the match with only the non-dot characters (the digits), which were captured in group #1.
$input="1.1.1.1";
$s = explode(".",$input ) ;
$t=array_slice($s, 1);
print implode(".",array($s[0] , implode("",$t)) );
or
$input="1.1.1.1";
$s = explode(".",$input ,2) ;
$s[1]=str_replace(".","",$s[1]);
print implode(".",array($s[0] ,$s[1] ) );
Match&Release the first occurring literal dot
Replace all subsequent literal dots
Code: (Demo)
echo preg_replace('~^[^.]*\.(*SKIP)(*FAIL)|\.~', '', $string);
// 1.101
Or with the "continue" character (\G), consume and forget the first literal dot, then replace all subsequent literal dots.
Code: (Demo)
echo preg_replace('~(?:^[^.]*\.|\G(?!^))[^.]*\K\.~', '', $string);
// 1.101
Or simply check that a literal dot has a literal dot occurring earlier in the string.
Code: (Demo)
echo preg_replace('~(?<=\.)[^.]*\K\.~', '', $string);
// 1.101
I though substr_replace() would work here, but sadly no... Here is a regex approach:
$str = preg_replace('~(\d+\.)(\d+)\.(\d+)\.(\d+)~', '$1$2$3$4', $str);
You could also try the below regex with s switch,
<?php
$string = '1.1.0.1';
$pattern = "/(?s)((?<=\.).*?)(\.)/i";
$replacement = "$1";
echo preg_replace($pattern, $replacement, $string);
?>
Output:
1.101
Using regex matches can be clearer by depicting the desired result and avoids the error-prone approach of calls to substr and strpos. Here I assume that no text is required before the first dot, i.e., that an input may begin with a dot that must be preserved. The difference is whether a quantifier of * or + is appropriate in the patterns below.
If your inputs will always be short, a straightforward approach is to replace trailing dots until none remain:
$count = 0;
$output = $input;
do {
$output = preg_replace('/^(.*\.)(.+)\./', '$1$2', $output, -1, $count);
} while ($count != 0);
echo $output;
To do it with a single regex match, use preg_replace_callback to apply a function (str_replace in this case) to the backreference variable $2.
$output = preg_replace_callback(
'/^([^.]*\.)(.+)$/',
function ($m) { return $m[1] . str_replace('.', '', $m[2]); },
$input);
Sample results:
1.1.0.1 - 1.101
.1.0.1 - .101
111 - 111
1.1 - 1.1
1. - 1.
.1 - .1
.1. - .1
.... - .
You may want to experiment with the code and test cases at Try It Online!

Categories