I have some values like 4,3 or 5 for instance.
I want to allow only the numbers (from 0 to 9) and the comma.
I found this function, pregmatch but it's not working correctly.
<?php
$regex="/[0-9,]/";
if(!preg_match($regex, $item['qty'])){
// my work
}
?>
What's wrong ?
Thanks
Corrected syntax:
$regex="/^[0-9,]+$/";
^ represents start of line
+ represents one or more of the group characters
$ represents end of line
This should do it:
'~^\d+(,\d+)?$~'
It allows e.g. 1 or 11,5 but fails on 1, or ,,1 or ,,
^ Start of
\d+ followed by one or more digits
(,\d+)? optional: comma , followed by one or more digits
$ end
\d is a shorthand for digit [0-9]
You asked what's wrong with $regex="/[0-9,]/";
It would match any 0-9 or , which are in the [characterclass]. Even, when matching a string like abc1s or a,b because no anchors are used.
If you know it will be a comma-separated list then use explode():
<?php
// test item with incorrect entries
$item = '1,2,3,4,d,#,;';
// explode whatever is between commas into an array
$item_array = explode(',', $item);
// loop through the array (you could also use array_walk())
foreach($item_array as $key => $val)
{
// to clean it
$item_array[$key] = (int) $val;
// use the values here
}
// or here
?>
<?php
$regex = '/^[0-9,]+$/';
if(!preg_match($regex, $item['qty'])) {
// my work
}
?>
Related
I have this string
$s = "red2 blue5 black4 green1 gold3";
I need to order by the number, but can show the numbers.
Numbers will always appears at the end of the word.
the result should be like:
$s = "green red gold black blue";
Thanks!
Does it always follow this pattern - separated by spaces?
I would break down the problem as such:
I would first start with parsing the string into an array where the key is the number and the value is the word. You can achieve this with a combination of preg_match_all and array_combine
Then you could use ksort in order to sort by the keys we set with the previous step.
Finally, if you wish to return your result as a string, you could implode the resulting array, separating by spaces again.
An example solution could then be:
<?php
$x = "red2 blue5 black4 green1 gold3";
function sortNumberedWords(string $input) {
preg_match_all('/([a-zA-Z]+)([0-9]+)/', $input, $splitResults);
$combined = array_combine($splitResults[2], $splitResults[1]);
ksort($combined);
return implode(' ', $combined);
}
echo sortNumberedStrings($x);
The regex I'm using here matches two seperate groups (indicated by the brackets):
The first group is any length of a string of characters a-z (or capitalised). Its worth noting this only works on the latin alphabet; it won't match รถ, for example.
The second group matches any length of a string of numbers that appears directly after that string of characters.
The results of these matches are stored in $splitResults, which will be an array of 3 elements:
[0] A combined list of all the matches.
[1] A list of all the matches of group 1.
[2] A list of all the matches of group 2.
We use array_combine to then combine these into a single associative array. We wish for group 2 to act as the 'key' and group 1 to act as the 'value'.
Finally, we sort by the key, and then implode it back into a string.
$s = "red2 blue5 black4 green1 gold3";
$a=[];
preg_replace_callback('/[a-z0-9]+/',function($m) use (&$a){
$a[(int)ltrim($m[0],'a..z')] = rtrim($m[0],'0..9');
},$s);
ksort($a);
print " Version A: ".implode(' ',$a);
$a=[];
foreach(explode(' ',$s) as $m){
$a[(int)ltrim($m,'a..z')] = rtrim($m,'0..9');
}
ksort($a);
print " Version B: ".implode(' ',$a);
preg_match_all("/([a-z0-9]+)/",$s,$m);
foreach($m[1] as $i){
$a[(int)substr($i,-1,1)] = rtrim($i,'0..9');
}
ksort($a);
print " Version C: ".implode(' ',$a);
Use one of them, but also try to understand whats going on here.
I have a user-input string with 2 comma-delimited integers.
Example (OK):
3,5
I want to reject any user input that contains leading 0's for either number.
Examples (Bad):
03,5
00005,3
05,003
Now what I could do is separate the two numbers into 2 separate string's and use ltrim on each one, then see if they have changed from before ltrim was executed:
$string = "03,5";
$string_arr = explode(",",$string);
$string_orig1 = $string_arr[0];
$string_orig2 = $string_arr[1];
$string_mod1 = ltrim($string_orig1, '0');
$string_mod2 = ltrim($string_orig2, '0');
if (($string_mod1 !== $string_orig1) || ($string_mod2 !== $string_orig2)){
// One of them had leading zeros!
}
..but this seems unnecessarily verbose. Is there a cleaner way to do this? Perhaps with preg_match?
You could shorten the code and check if the first character of each part is a zero:
$string = "03,5";
$string_arr = explode(",",$string);
if ($string_arr[0][0] === "0" || $string_arr[1][0] === "0") {
echo "not valid";
} else {
echo "valid";
}
Here is one approach using preg_match. We can try matching for the pattern:
\b0\d+
The \b would match either the start of the string, or a preceding comma separator.
If we find such a match, it means that we found one or more numbers in the CSV list (or a single number, if only one number present) which had a leading zero.
$input = "00005,3";
if (preg_match("/\b0\d+/", $input)) {
echo "no match";
}
You can do a simple check that if the first character is 0 (using [0]) or that ,0 exists in the string
if ( $string[0] == "0" || strpos($string, ",0") !== false ) {
// One of them had leading zeros!
}
All the current answers fail if any of the values are simply 0.
You can just convert to integer and back and compare the result.
$arr = explode(',', $input);
foreach($arr as $item) {
if( (str)intval($item) !== $item ) {
oh_noes();
}
}
However I am more curious as to why this check matters at all.
One way would be with /^([1-9]+),(\d+)/; a regex that checks the string starts with one or more non-zero digits, followed by a comma, then one or more digits.
preg_match('/^([1-9]+),(\d+)/', $input_line, $output_array);
This separates the digits into two groups and explicitly avoids leading zeros.
This can be seen on Regex101 here and PHPLiveRegex here.
I don't know what the title of the question should be. This something logical and what I lack is the same.
I have a string in the format [CONST att1="value1" att2="value2"] and created a regex that was working fine. But certain conditions made this regex wrong.
$data = preg_split('/(?<=\")\s/', $replace_str[1]);
foreach ($data as $index_val => $exp_data) {
if(!empty($exp_data)){
$attributes = explode('=',$exp_data);
if(count($attributes) > 0){
$index = strtolower(str_replace(array("'", "\""), "", trim($attributes[0])));
$item_value = str_replace(array("'", "\""), "", trim($attributes[1]));
$item_value = $attributes[1];
$array_data[$index] = $item_value;
}
}
}
Then using the array to get key value. But in some instance, say if the format is like the one below
[CONST att1="value1" att2= "value2"]
the exploded variable contains "value2" (notice the prefixed space). What i want is "value2".
So since my format is similar to that of WordPress shortcode referred shortcode.php file in WordPress and found #[<>&/\[\]\x00-\x20=]# inside the file. But I am unable to understand or make it work.
I need to access value1 and value2 as clean data. i.e, without spaces, single and double quotes at the start and end. Also if the order of the att1 and att2 is changed, it should work.
[CONST att2="value2" att1="value1"]
Should output:
array(att1=>value1,att2=>value2)
I suggest collecting keys and values in the shortcode string using a matching regex with preg_match_all like
'~(?:\G(?!\A)\s+|^\[\w+\s+)\K([^\s=]*)\s*=\s*"([^"]*)"~'
See the regex demo.
Details
(?:\G(?!\A)\s+|^\[\w+\s+)
\K - match reset operator
([^\s=]*) - Group 1 (attribute name): 0+ chars other than whitespace and =
\s*=\s* - a = enclosed with 0+ whitespaces
" - a double quotation mark
([^"]*) - Group 2 (attribute value inside quotes): any 0+ chars other than "
" - a double quotation mark
After you get an array of matches you will have to build your associative array "manually" like
$s = '[CONST att1="value1" att2="value2"]';
preg_match_all('/(?:\G(?!\A)\s+|^\[\w+\s+)\K(\w+)\s*=\s*"([^"]*)"/', $s, $array_data, PREG_SET_ORDER, 0);
$res = [];
foreach ($array_data as $kvp) {
$res[$kvp[1]] = $kvp[2];
}
print_r($res);
// -> Array ( [att1] => value1 [att2] => value2 )
See the PHP demo.
Another way of processing the matches (demo):
if (preg_match_all('/(?:\G(?!\A)\s+|^\[\w+\s+)\K(\w+)\s*=\s*"([^"]*)"/', $s, $array_data)) {
array_shift($array_data);
print_r(array_combine($array_data[0], $array_data[1]));
}
I have this autogenerated variable:
$var = "WXYZ 300700Z 32011KT 9999 FEW035 SCT200 24/16 Q1007 NOSIG";
How can I search and save "9999" in this var? I cant use substr cause $var's value is always changing and it is always in another "place" in the variable. It is always 4 numbers.
You can match 4 numbers wrapped by word boundaries or space characters, depending on what you need with regular expression (regex/regexp).
if( preg_match('/\b([0-9]{4})\b/', $var, $matches) > 0 ) {
// $matches[1] contains the number
}
Note, however, that the word boundary match will also match on non-letter characters (symbols like dollar sign ($), hyphen (-), period (.), comma (,), etc.). So a string of "XYZ ABC 9843-AB YZV" would match the "9843". If you want to just match based on numbers surrounded by white space (spaces, tabs, etc) you can use:
if( preg_match('/(?:^|\s)([0-9]{4})(?:\s|$)/', $var, $matches) > 0 ) {
// $matches[1] contains the number
}
Using explode is the way to go, we need to turn the string into an array, our variables are separated by white space, so we get a variable every time we face a white space " ", i made another example to understand how explode works.
<?php
$var = "WXYZ 300700Z 32011KT 9999 FEW035 SCT200 24/16 Q1007 NOSIG";
print_r (explode(" ",$var)); //Display the full array.
$var_search = explode(" ",$var);
echo $var_search[3];//To echo the 9999 (4th position).
?>
<br>
<?php
$var = "WXYZ+300700Z+32011KT+9999+FEW035+SCT200+24/16+Q1007+NOSIG";
print_r (explode("+",$var)); //Display the full array.
$var_search = explode("+",$var);
echo $var_search[3];//To echo the 9999 (4th position).
?>
I hop this is what you're looking for
Is this viable?
$var = "WXYZ 300700Z 32011KT 9999 FEW035 SCT200 24/16 Q1007 NOSIG";
if (strpos($var, '9999') == true {
// blah blah
}
else{
echo 'Value not found'
}
Personally haven't tested this yet, but I think you're looking for something along these lines...
Hello I would use a preg_match regex using this regular expression : \d{4}
here is the solution
var str1 = "WXYZ 300700Z 32011KT 9999 FEW035 SCT200 24/16 Q1007 NOSIG";
var str2 = "9999";
if(str1.indexOf(str2) != -1){
console.log(str2 + " found");
}
Say I have this user list:
Michael (43)
Peter (1) (143)
Peter (2) (144)
Daniel (12)
The number in the furthest right set of parentheses is the user number.
I want to loop each user and get the highest user number in the list, which in this case would be 144.
How do I do this? I'm sure it can be done with some kind of regexp, but I have no idea how. My loop is simple:
$currentUserNO = 0;
foreach ($users as $user) {
$userNO = $user->NameUserNo; // NameUserNo is the string to be stripped! ex: "Peter (2) (144)" => 144
if ($userNO > $currentUserNO) {
$currentUserNO = $userNO;
}
}
echo "The next user will be added with the user number: " . $currentUserNO + 1;
You could use a regex like:
/\((\d+)\)$/
^ glued to the end of the string
^^ closing parentheses
^^^ the number you want to capture
^^ opening parentheses
to capture the number in the last set of parentheses / at the end of the string.
But you could also use some basic array and string functions:
$parts = explode('(', trim($user->NameUserNo, ' )'));
$number = end($parts);
which breaks down to:
trim the closing parentheses and spaces from the end (strictly speaking from the beginning and end, you could also use rtrim());
explode on the opening parentheses;
get the last element of the resulting array.
If you are not confortable with regular expression you should not use them (and start to seriously learn them* as they are very powerful but cryptic).
In the mean time you don't have to use regex to solve your problem, just use (assuming that the NameUserNo contains just a line of the list) :
$userNO = substr(end(explode('(',$user->NameUserNo;)),0,-1);
It should be easier to understand.
* Is there a good, online, interactive regex tutorial?
I think the regular expression you are looking for is:
.+\((\d+)\)$
Which should select all characters until it reaches the last number wrapped in parenthesis.
The PHP code you can use to extract just the number is then:
$userNO = preg_replace('/.+\((\d+)\)$/', '$1', $user);
I haven't tested this, but it should set $userNO to 43 for the user Michael and 143 for the user Peter and so on.
I guess this is basically what you are looking for:
<?php
$list = array();
foreach $users as $user) {
preg_match('/$([a-zA-Z]+).*\([1-9]+\)$/', , $tokens);
$list[$tokens[2]] = $tokens[1];
}
ksort($list);
$highest = last(array_keys($list));
echo "The next user will be added with the user number: " . $highest++;
This is pretty easy to do with a regex.
foreach ($users as $user) {
# search for any characters then a number in brackets
# the match will be in $matches[1]
preg_match("/.+\((\d+)\)/", $user->NameUserNo, $matches);
$userNO = $matches[1];
if ($userNO > $currentUserNO) {
$currentUserNO = $userNO;
}
}
Because regexs use greedy matching, the .+, which means search for one or more characters, will grab up as much of the input string as it can before it reaches the number in brackets.
I'm fairly new to PHP, but couldn't you do it with:
$exploded = explode(" ", $user->NameUserNumber);
$userNo = substr(end($exploded), 1,-1);