Please forgive me if this question appears too cheap.
I have this line:
preg_match_all($pattern, $_GET['id'], $arr);
When you pass a value with space during a search, the value breaks once a space is encountered.
For instance:
36 2543541284
Notice a space between 6 and 2. In a situation similar to this, only 36 is displayed.
The reminder of digits after space are ignored. This is giving users, "no data found" message.
I have tried using urlencode to add 20% but no luck.
preg_match_all($pattern, rawurlencode($_GET[id]), $arr);
I have also tried urlencode but to no avail.
What am I possibly doing wrong?
function format($matches)
{
return $matches[1][0].(strlen($matches[2][0])>0?$matches[2][0]:" ").$matches[3][0].(strlen($matches[4][0])>0?" ".$matches[4][0]:"");
}
// CONSTRUCT A REGULAR EXPRESSION
$pattern
= '/' // regex delimiter
. '(' // START of a capture group
. '\d{2}' // exactly two digits
. ')' // END of capture group
. '(' // START SECOND capture group
. '[ND]?' // letters "D" OR "N" in any order or number - This is optional
. ')' // END SECOND capture group
. '(' // START THIRD capture group
. '\d*' // any number of digits
. ')' // END THIRD capture group
. '(' // START FOURTH capture group
. 'GG' // the letters "GG" EXACTLY
. '[\d]*' // any number of digits
. ')' // END THIRD capture group
. '?' // make the LAST capture group OPTIONAL
. '/' // regex delimiter
;
preg_match_all($pattern, rawurlencode($_GET[id]), $arr);
// REFORMAT the array
$str = format($arr);
// show what we did to the data
echo '<pre>' . PHP_EOL;
echo '1...5...10...15...20...' . PHP_EOL;
echo $pattern;
echo PHP_EOL;
//Are we getting what we asked for? This is a test. We will comment out all 6 lines if we are happy with output of our REFORMATTING.
echo $str;
echo PHP_EOL;
Your regex as it stands will not match two digits followed by a space and further digits.
If you want it to, you could change [ND]? to [\sND]?, although this would also allow a space if the string wasn't all digits.
You need to specify the rules precisely if you want further advice on the regex.
Regex is an overkill in this case.
From the urlencode manual:
Returns a string in which all non-alphanumeric characters except -_.
have been replaced with a percent (%) sign followed by two hex digits
and spaces encoded as plus (+) signs. It is encoded the same way that
the posted data from a WWW form is encoded, that is the same way as in
application/x-www-form-urlencoded media type. This differs from the ยป
RFC 3986 encoding (see rawurlencode()) in that for historical reasons,
spaces are encoded as plus (+) signs.
It clearly states that if you want spaces to be encoded as %20, and not +, you should use rawurlencode().
Code example:
$strings = array(
'36 2543541284',
'1234 5678',
'this is a string'
);
$strings_encoded = array();
foreach($strings as $string)
{
$strings_encoded[] = rawurlencode($string);
}
var_dump($strings_encoded);
Outputs:
array(3) {
[0]=>
string(15) "36%202543541284"
[1]=>
string(11) "1234%205678"
[2]=>
string(22) "this%20is%20a%20string"
}
Related
I'am doing a project which is cleaning text with php.
say that i have string like this :
$string = 'Life is like. . . . . . a box of chocolate. . . . . '; //each dot separated by space
How can i get the output like
$string ='Life is like a box of chocolate';
You can use preg_replace
$string = 'Life is like. . . . . . a box of chocolate. . . . . ';
echo preg_replace('/[.,]/', '', $string);
If your expected result is just to strip the dots and surrounding spaces, you can use preg_replace, but to get your expected result you need a bit more complex regex:
echo preg_replace(array("/(?<!\w) *\. */", "/(?<=\w)\. */"), array("", " "), $string);
Here I use an array of two regex to match two different cases:
a dot followed and preceded by 0 or more spaces, all preceded by a character which is not a letter or a digit (\w in regex means a letter or a digit, and this is a negative lookbehind). This is substituted by an empty string.
a dot followed by 0 or more spaces, and preceded by a letter or a digit. This is substituted by a space.
2 is to match and remove the dot in 'like. ' but leave a single space after the word.
This gives your expected result: 'Life is like a box of chocolate'
You can learn more on regex (short for regular expression) looking for tutorials on the web.
isn't it an easy str_replace()?
str_replace(". ", "", $text);
My goal is getting something like that: 150.000,54 or 48.876,05 which means my commas are decimal starters.
Here's my code so far :
<?php
//cut numbers after comma if there are any, after 2 digits
$matchPattern = '/[0-9]+(?:\,[0-9]{2}){0,2}/';
//remove everything except numbers, commas and dots
$repl1 = preg_replace("/[^a-zA-Z0-9,.]/", "", $input);
//let there be a 0 before comma to have values like 0,75
$repl2 = preg_replace("/^[0]{1}$/", "",$repl1);
//now i need you here to help me for the expression putting dots after each 3 numbers, until the comma:
$repl3 = preg_replace("/regexphere$/", ".", $repl2);
preg_match($matchPattern, $repl3, $matches);
echo($matches[0]);
?>
I know preg_replacing 3 times is stupid but I am not good at writing regular expressions. If you have a better idea, don't just share it but also explain. I know a little of the types : http://regexone.com/lesson/0
Thank you in advance.
--------UPDATE--------
So I need to handle 0000,45 like inputs to 0,45 and like 010101,84 inputs to 1,84
When this is done, I'm done.
$input = Input::get('userinput');
$repl1 = preg_replace("/[^0-9,.]/", "", $input);
$repl2 = preg_replace("/^0/", "",$repl1);
$repl3 = str_replace(".","",$repl2);
preg_match('/[0-9]+(?:\,[0-9]{2}){0,2}/', $repl3, $matches);
$repl4 = preg_replace('/(\d)(?=(\d{3})+(?!\d))/', '$1.', $matches[0]);
return repl4;
----UPDATE----
Here's what i get so far : https://ideone.com/5qmslB
I just need to remove the zeroes before the comma, before the numbers.
I am not sure this is the best way, but I hope it is helpful.
Here is the updated code that I used with a fake $input:
<?php
$input = "textmdwrhfejhg../,2222233333,34erw.re.ty";
//cut numbers after comma if there are any, after 2 digits
$matchPattern = '/[0-9]+(?:\,[0-9]{2}){0,2}/';
//remove everything except numbers, commas and dots
$repl1 = trim(preg_replace("/[^0-9,.]/", "", $input), ".,");
echo "$repl1" . "\n";
//let there be a 0 before comma to have values like 0,75, remove the 0
$repl2 = preg_replace("/^0/", "",$repl1);
echo "$repl2" . "\n";
//The expression putting dots after each 3 numbers, until the comma:
$repl3 = preg_replace('/(\d)(?=(?:\d{3})+(?!\d))/', '$1.', $repl2);
echo "$repl3" . "\n";
The expression putting dots after each 3 numbers is
(\d)(?=(?:\d{3})+(?!\d))
Here, you can see how it works. In plain human,
(\d) - A capturing group that we'll use in the replacement pattern, matching a single digit that....
(?=(?:\d{3})+(?!\d)) - is followed by groups of 3 digits. External (?=...) is a look-ahead construction that checks but does not consume characters, (?:\d{3})+ is a non-capturing group (no need to keep the matched text in memory) that matches 3 digits exactly (due to the limiting quantifier {3}) 1 or more times (due to the + quantifier), and (?!\d) is a negative look-ahead checking that the next character after the last matched 3-digit group is not a digit.
This does not work in case we have more than 3 digits after a decimal separator. With regex, I can only think of a way to support 4 digits after decimal with (?<!,)(\d)(?=(?:\d{3})+(?!\d)). Not sure if there is a generic way without variable-width look-behind in PHP (as here, we also need a variable-width look-ahead, too). Thus, you might consider splitting the $repl2 value by comma, and only pass the first part to the regex. Then, combine. Something like this:
$spl = split(',', $repl2); // $repl2 is 1234,123456
$repl3 = preg_replace('/(\d)(?=(?:\d{3})+(?!\d))/', '$1.', $spl[0]);
$repl3 .= "," . $spl[1]; // "1.234" + "," + "123456"
echo "$repl3" . "\n"; // 1.234,123456
Update:
The final code I have come up with:
$input = "textmdwrhfejhg../0005456,2222233333,34erw.re.ty";
//Here's mine :
$repl1 = trim(preg_replace("/[^0-9,.]/", "", $input), '.,');
//following line just removes one zero, i want it to remove all chars like
//Input : 000549,569 Output : 549,569
echo "$repl1\n";
$repl2 = preg_replace("/^0+(?!,)/", "",$repl1);
$repl3 = str_replace(".","",$repl2);
preg_match('/[0-9]+(?:\,[0-9]{2}){0,2}/', $repl3, $matches);
$repl4 = preg_replace('/(\d)(?=(\d{3})+(?!\d))/', '$1.', $matches[0]);
echo $repl4;
Hello i have a regex which accepts mostly every character including specials.And i have set
it to accept minimum 8 and maximum 30 characters.
Everything is right for minimum but it's not working for maximum.
If string is more than 30 or any length. The result is true.
The pattern is here:
$pattern = '/[A-Za-z0-9' . preg_quote( '.%^&()$##!/-+/', '/') . ']{8,30}/';
The whole testing code is:
$pattern = '/^[A-Za-z0-9' . preg_quote( '.%^&()$##!/-+/', '/') . ']{8,30}$/';
if(preg_match($pattern, $pass))
{
echo '<br>true';
}
else
{
echo '<br>false';
}
?>
This will match any string up to 30 characters within the string. You need to include the start and end of the string:
$pattern = '/^[A-Za-z0-9' . preg_quote( '.%^&()$##!/-+/', '/') . ']{8,30}$/';
The first $pattern expression in your question is missing the required: ^ and $ beginning and end of line assertions - (but the example code snippet which follows uses them correctly.)
You also need to escape the dash/hyphen inside the character class - the hyphen defines a range of characters. (Note that the forward slash / is NOT the escape char!) Try this:
$pattern = '/^[A-Za-z0-9.%^&()$##!\-+\/]{8,30}$/';
I'm having troubles finding a regex that can retrieve the numbers 989552 in
/boards/989552-lettersandnumbers-morelettersandnumbers
What I'm searching in particular is can I retrieve what stands between /boards/ and the first -?
/boards/(\d+)-
Should store the numbers in the first match group.
Use .*/(\d+)- as .* is greedy it will match upto the last /:
$string = "/boards/989552-dgw25235-42352gdsgw";
echo preg_match('#.*/(\d+)-#',$string,$match);
echo $match[1];
>>> 989552
Here is an annotated solution.
<?php // RAY_temp_user1722791.php
error_reporting(E_ALL);
/*
I'm having troubles finding a regex that can retrieve the numbers 989552 in /boards/989552-lettersandnumbers-morelettersandnumbers
What I'm searching in particular is can I retrieve what stands between /boards/ and the first -?
*/
// A REGULAR EXPRESSION
$rgx
= '#' // REGEX DELIMITER
. '/boards/' // THE SEARCH STRING
. '(' // START A GROUP
. '\d+' // SOME DIGITS
. ')' // END OF THE GROUP
. '-' // THE DASH
. '#' // REGEX DELIMITER
;
// A TEST STRING
$str = 'in /boards/989552-lettersandnumbers';
// PEFORM THE MATCH
preg_match($rgx, $str, $mat);
// FIND THE NUMBERS IN THE FIRST MATCHED GROUP
var_dump($mat[1]);
I find it much easier to understand regular expressions when I write them out in vertical notation like this.
How to replace part of a string based on a "." (period) character
only if it appears after/before/between a word(s),
not when it is before/between any number(s).
Example:
This is a text string.
-Should be able to replace the "string." with "string ."
(note the Space between the end of the word and the period)
Example 2
This is another text string. 2.0 times longer.
-Should be able to replace "string." with "string ."
(note the Space between the end of the word and the period)
-Should Not replace "2.0" with "2 . 0"
It should only do the replacement if the "." appears at the end/start of a word.
Yes - I've tried various bits of regex.
But everything I do results in either nothing happening,
or the numbers are fine, but I take the last letter from the word preceeding the "."
(thus instead of "string." I end up with "strin g.")
Yes - I've looked through numerous posts here - I have seen Nothing that deals with the desire, nor the "strange" problem of grabbing the char before the ".".
You can use a lookbehind (?<=REXP)
preg_replace("/(?<=[a-z])\./i", "XXX", "2.0 test. abc") // <- "2.0 testXXX abc"
which will only match if the text before matches the corresponding regex (in this case [a-z]). You may use a lookahead (?=REXP) in the same way to test text after the match.
Note: There is also a negative lookbehind (?<!REXP) and a negative lookahead (?!REXP) available which will reject matches if the REXP does not match before or after.
$input = "This is another text string. 2.0 times longer.";
echo preg_replace("/(^\.|\s\.|\.\s|\.$)/", " $1", $input);
http://ideone.com/xJQzQ
I'm not too good with the regex, but this is what I would do to accomplish the task with basic PHP. Basically explode the entire string by it's . values, look at each variable to see if the last character is a letter or number and add a space if it's a number, then puts the variable back together.
<?
$string = "This is another text string. 2.0 times longer.";
print("$string<br>");
$string = explode(".",$string);
$stringcount = count($string);
for($i=0;$i<$stringcount;$i++){
if(is_numeric(substr($string[$i],-1))){
$string[$i] = $string[$i] . " ";
}
}
$newstring = implode('.',$string);
print("$newstring<br>");
?>
It should only do the replacement if the "." appears at the end/start of a word.
search: /([a-z](?=\.)|\.(?=[a-z]))/
replace: "$1 "
modifiers: ig (case insensitive, globally)
Test in Perl:
use strict;
use warnings;
my $samp = '
This is another text string. 2.0 times longer.
I may get a string of "this and that.that and this.this 2.34 then that 78.01."
';
$samp =~ s/([a-z](?=\.)|\.(?=[a-z]))/$1 /ig;
print "$samp";
Input:
This is another text string. 2.0 times longer.
I may get a string of "this and that.that and this.this 2.34 then that 78.01."
Output:
This is another text string . 2.0 times longer .
I may get a string of "this and that . that and this . this 2.34 then that 78.01."