I'm trying build a regex that will replace any characters not of the format:
any number of digits, then optional (single decimal point, any number of digits)
i.e.
123 // 123
123.123 // 123.123
123.123.123a // 123.123123
123a.123 // 123.123
I am using ereg_replace in php and the closest to a working regex i have managed is
ereg_replace("[^.0-9]+", "", $data);
which is almost what i need (apart from it will allow any number of decimal points)
i.e.
123.123.123a // 123.123.123
my next attempt was
ereg_replace("[^0-9]+([^.]?[^0-9]+)?", "", $data);
which was meant to translate as
[^0-9]+ // any number of digits, followed by
( // start of optional segment
[^.]? // decimal point (0 or 1 times) followed by
[^0-9]+ // any number of digits
) // end of optional segment
? // optional segment to occur 0 or 1 times
but this just seems to allow any number of digits and nothing else.
Please help
Thanks
Try these steps:
remove any character except 0-9 and .
remove any . behind the first decimal point.
Here’s a implementation with regular expressions:
$str = preg_replace('/[^0-9.]+/', '', $str);
$str = preg_replace('/^([0-9]*\.)(.*)/e', '"$1".str_replace(".", "", "$2")', $str);
$val = floatval($str);
And another one with just one regular expression:
$str = preg_replace('/[^0-9.]+/', '', $str);
if (($pos = strpos($str, '.')) !== false) {
$str = substr($str, 0, $pos+1).str_replace('.', '', substr($str, $pos+1));
}
$val = floatval($str);
This should be faster, actually. And it is way more readable. ;-)
$s = preg_replace('/[^.0-9]/', '', '123.123a.123');
if (1 < substr_count($s, '.')) {
$a = explode('.', $s);
$s = array_shift($a) . '.' . implode('', $a);
}
Related
Iv seeing some answers like: Add space after every 4th character using
echo wordwrap('1234567890' , 4 , '-' , true )
But in this case I need to count the characters from right to left.
For example to format a phone number user friendly 123-123-1234. The problem is that sometimes the user could submit a code area, and If I start normally left to right I can get this: 012-312-3123-4 So I am thinking of starting right to left.
Any ideas?
A regex with a lookahead assertion that there are one or more groups of 4 characters between the matched position and the end of the string should do this for you.
echo preg_replace("/(?=(.{4})+$)/", "-", "1234567890");
// 12-3456-7890
You'll need to handle strings with an exact multiple of 4 characters which will end up with a hyphen at the beginning. You could either add a lookbehind assertion to the regex or it might be easier to read if you trim the hyphen off afterwards.
echo preg_replace("/(?=(.{4})+$)/", "-", "123456789012");
// -1234-5678-9012
echo preg_replace("/(?<=.)(?=(.{4})+$)/", "-", "123456789012");
// 1234-5678-9012
echo ltrim(preg_replace("/(?=(.{4})+$)/", "-", "123456789012"), "-");
// 1234-5678-9012
This works
function myFormat($s, $len, $delimiter = "-")
{
$techChar = " ";
$newLen = ceil(strlen($s) / $len) * $len;
$s = str_pad($s, $newLen, $techChar, STR_PAD_LEFT);
$s = wordwrap($s, $len, $delimiter, true);
$s = ltrim($s, $techChar);
return $s;
}
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 have data in this format coming from a database...
BUS 101S Business and Society
or
BUS 101 Business and Society
Notice the optional "S" character (which can be any uppercase character)
I need to replace the "BUS 101S" part with null and here is what I have come up with...
$value = "BUS 101S Business and Society";
$sub = substr($value, 0, 3); // Gives me "BUS"
$num = substr($value, 4, 3); // Gives me "101"
$new_value = preg_replace("/$sub $num"."[A-Z]?/", null, $value);
The value of $new_value now contains S Business and Society. So I'm close, Just need it to replace the optional single uppercase character as well. Any ideas?
Assuming the pattern is 3 uppercase letters, 3 numbers and then an optional uppercase letter, just use a single preg_match:
$new = preg_replace('/^[A-Z]{3} \d{3}[A-Z]?/', '', $old);
The ^ will only match at the beginning of a line/string. The {3} means "match the preceding token 3 times exactly". The ? means "match the preceding token zero or one times"
You can also do something like this, so you don't bother with substr:
preg_replace('#^[A-Z]{3} [0-9]{3}[A-Z]? (.*)$#', '$1', $value);
Or using preg_match, to get all the components of the string
if (preg_match('#^([A-Z]{3}) ([0-9]{3})([A-Z]?) (.*)$#', $value, $matches)) {
$firstMatch=$matches[1];//BUS ($matches[0] is the whole string)
$secondMatch=$matches[2];//101
$secondMatch=$matches[3];//S or ''
$secondMatch=$matches[4];//the rest of the text
}
Wouldn't it just be easier to do something like:
$str = 'BUS 101S Business and Society';
$words = explode(' ', $str);
array_unshift($words); // bus
array_unshift($words); // 101s
$str = implode(' ', $words);
Does anyone know how can I cut only number or char from the string in php?
Example
$test = '12b';
any way that I can only cut the number from the variable: 12?
also and way that I can only cut out the char: b?
NOTE: the $test string flexible to changed.. means it could come with '123b', '1a'...
preg_match could be made use of:
<?php
$test = '12b';
preg_match( '/^(\d+)(\w+)$/', $test, $matches );
$digits = $matches[1];
$characters = $matches[2];
?>
Try this:
$test='12b';
// ...
$numeric = preg_replace('/[^\d]/', '', $test);
echo $numeric; // 12
$alpha = preg_replace('/[^a-z]/i', '', $test);
echo $alpha; // b
This will work for any combination of characters. All the digits will appear in $numeric, and all latin alphabet letters will appear in $alpha.
This will still work if the letters and numbers are reversed, or if other symbols appear in the string.
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!