Get string between first and third occurence of character - php

I have many Strings looking like this:
QR-DF-6549-1 and QR-DF-6549
I want to get these parts of the strings:
DF-6549
Edit:
So I also want to get rid of the "-1" at the end, in case it exists.
How can I do this with php? I know substr but I am a bit lost at this one.
Thank you very much!

A regular expression is probably the best way given your sample data
// ^ start matching at start of string
// [A-Z]{2}- must start with two capital letters and a dash
// ( we want to capture everything that follows
// [A-Z]{2}- next part must start with two capital letters and a dash
// \d+ a sequence of one or more digits
// ) end the capture - this will be index 1 in the $match array allowed
if (preg_match('/^[A-Z]{2}-([A-Z]{2}-\d+)/', $str, $match)) {
$data=$match[1];
}

Related

split a value into two and then reverse the value in php

I have a value like this 73b6424b. I want to split value into two parts. Like 73b6 and 424b. Then the two split value want to reverse. Like 424b and 73b6. And concatenate this two value like this 424b73b6. I have already done this like way
$substr_device_value = 73b6424b;
$first_value = substr($substr_device_value,0,4);
$second_value = substr($substr_device_value,4,8);
$final_value = $second_value.$first_value;
I am searching more than easy way what I have done. Is it possible?? If yes then approach please
You may use
preg_replace('~^(.{4})(.{4})$~', '$2$1', $s)
See the regex demo
Details
^ - matches the string start position
(.{4}) - captures any 4 chars into Group 1 ($1)
(.{4}) - captures any 4 chars into Group 2 ($2)
$ - end of string.
The '$2$1' replacement pattern swaps the values.
NOTE: If you want to pre-validate the data before swapping, you may replace . pattern with a more specific one, say, \w to only match word chars, or [[:alnum:]] to only match alphanumeric chars, or [0-9a-z] if you plan to only match strings containing digits and lowercase ASCII letters.

Regex to check a valid number in a format in PHP

I want to check if the string is in the following format
YYMMDD-XXXX
YYYYMMDD-XXXX
YYMMDDXXXX
YYYYMMDDXXXX
I have this regex
^\d{6,8}(-\d{4})?$
But then I am stuck. I am really new at regex. Can I get some help or some pointers?
Make the - optional and your regex works:
^\d{6,8}(-?\d{4})?$
https://regex101.com/r/uoF1HM/1/
This also would match many number formats though. Your example strings look like dates, if that is the case I'd use something stricter ( or already written e.g. https://stackoverflow.com/a/14566624/3783243 might be a good place to start).
You can use this function:
function checkFunc($value){
if (preg_match('/^[0-9]{6,8}(-?)[0-9]{4}$/', $value)) {
//is valid
return $value;
} else {
//is invalid
return false;
}
}
echo checkFunc("20180529-4444"); //20180529-4444
but for the first part of string, you will have to create different check for the date format
In your regex ^\d{6,8}(-\d{4})?$ youy have an optional group (-\d{4})? with a hyphen inside the group. That means that you can only match a format like \d{6,8} or with a hyphen \d{6,8}-\d{4} but not \d{6,8}\d{4} because the hyphen should be there according to the optional group.
If you want to match your values without any capturing groups you could make only the dash optional ?
That would match
^ Assert position at the start of the line
\d{6,8} Match 6 - 8 digits
-? Match optional dash
\d{4} Match 4 digits
$ Assert position at the end of the line
^\d{6,8}-?\d{4}$

Find nth character except if its enclosed in brackets php

I use the following function to find the nth character in a string which works well. However there is one exception, lets say its a comma for this purpose, what i need to alter about this is that if the coma is within ( and ) then it shouldnt count that
function strposnth($haystack, $needle, $nth=1, $insenstive=0)
{
//if its case insenstive, convert strings into lower case
if ($insenstive) {
$haystack=strtolower($haystack);
$needle=strtolower($needle);
}
//count number of occurances
$count=substr_count($haystack,$needle);
//first check if the needle exists in the haystack, return false if it does not
//also check if asked nth is within the count, return false if it doesnt
if ($count<1 || $nth > $count) return false;
//run a loop to nth number of occurrence
//start $pos from -1, cause we are adding 1 into it while searching
//so the very first iteration will be 0
for($i=0,$pos=0,$len=0;$i<$nth;$i++)
{
//get the position of needle in haystack
//provide starting point 0 for first time ($pos=0, $len=0)
//provide starting point as position + length of needle for next time
$pos=strpos($haystack,$needle,$pos+$len);
//check the length of needle to specify in strpos
//do this only first time
if ($i==0) $len=strlen($needle);
}
//return the number
return $pos;
}
So ive got the regex working that only captures the comma when outside of () which is:
'/,(?=[^)]*(?:[(]|$))/'
and you can see a live example working here:
http://regex101.com/r/xE4jP8
but im not sure how to make it work within the strpos loop, i know what i need to do, tell it the needle has this regex exception but i am not sure how to make it work. Maybe i should ditch the function and use another method?
Just to mention my end result i want is to split the string after every 6 commas before the next string starts, example:
rttr,ertrret,ertret(yes,no),eteert,ert ert,rtrter,0 rttr,ert(yes,no)rret,ert ret,eteert,ertert,rtrter,1 rttr,ertrret,ert ret,eteert,ertert,rtrter,0 rttr,ertrret,ert ret,eteert,ertert,rtrter,2 rttr,ert(white,black)rret,ert ret,eteert,ertert,rtrter,0 rttr,ertrret,ert ret,eteert,ertert,rtrter,0 rttr,ertrret,ert ret,et(blue,green)eert,ertert,rtrter,1
Note that there is always a 1 digit number (1-3) and a space after the 6th comma before the next part of the string begins but i cant really rely on that as its possible earlier in the string this pattern could happen so i can always rely on the fact ill need to split the string after the first digit and space after the 6th comma. So i want to split the string directly after this.
For example the above string would be split like this:
rttr,ertrret,ertret(yes,no),eteert,ert ert,rtrter,0
rttr,ert(yes,no)rret,ert ret,eteert,ertert,rtrter,1
rttr,ertrret,ert ret,eteert,ertert,rtrter,0
rttr,ertrret,ert ret,eteert,ertert,rtrter,2
rttr,ert(white,black)rret,ert ret,eteert,ertert,rtrter,0
rttr,ertrret,ert ret,eteert,ertert,rtrter,0
rttr,ertrret,ert ret,et(blue,green)eert,ertert,rtrter,1
I can do that myself pretty easily if i know how to get the position of the character then i can use substr to split it but an easier way might be preg_split but im not sure how that would work until i figure this part out
I hope i wasnt too confusing in explaining, i bet i was :)
For these kind of nesting problems regex usually is not the right tool. However, when the problem is actually not that complicated, as yours seems to be, regex will do just fine.
Try this:
(?:^|,)((?:[^,(]*(?:\([^)]*\))?)*)
^ start the search with a comma or the start of the string
^ start non capture group
^ search until comma or open parenthesis
^ if parenthesis found then capture until
^ end of parenthesis
^ end of capture group repeat if necessary
See it in action: http://regex101.com/r/eS0cX4
As you can see this will capture everything between the comma's outside of the parenthesis. If you get all these matches into an array using preg_match_all you can split it any which way you like.

Search a String for Alpha Numeric Characters in a Pattern

I have a string that contains 5 words. In the string one of the words is a Ham Radio Call Sign and can be anyone of the thousands of call signs in the US. In order to extract the Call Sign from the string I need to utilize the below pattern. The Call Sign I need to extract can be in any of the 5 positions in the string. The number is never the first character and the number is never the last character. The string is actually put together from an Array since it is originally read from a text file.
$string = $word[1] $word[2] $word[3] etc....
So the search can be either done on the whole string or each piece of the array.
Patterns:
1 Number and 3 Letters Example: AB4C A4BC
1 Number and 4 Letters Example: A4BCD
1 Number and 5 Letters Example: AB4CDE
I have tried everything I can think of and search till I cant search no more. I am sure I am over thinking this.
A two-step regular expression like this would do it:
$str = "hello A4AB there BC5AD";
$signs = array();
preg_match_all('/[A-Z][A-Z\d]{1,3}[A-Z]/', $str, $possible_signs);
foreach($possible_signs[0] as $possible_sign)
if (preg_match('/^\D+\d\D+$/', $possible_sign))
array_push($signs, $possible_sign);
print_r($signs); //Array ([0] => A4AB [1] => BC5AD)
Explanation
This is a regular expression approach, using two patterns. I don't think it could be done with one and still satisfy the exact requirements of the matching rules.
The first pattern enforces the following requirements:
substring starts and ends with a capital letter
substring contains only other capital letters or numbers between the first and last letter
substring is, overall, not more than 6 characters long
What I can't do in that same pattern, for complex REGEX reasons I won't go into (unless someone knows a way and can correct me), is enforce that only one number is contained.
#jeroen's answer does enforce this in a single pattern, but in turn does not enforce the correct length of the substring. Either way, we need a second pattern.
So after grabbing the initial matches, we loop over the results. We then apply each to a second pattern that enforces simply that there is only one number in the substring.
If so, we green-light the substring and it's added to the $signs array.
Hope this helps.
It depends on what the other words can contain, but you could use a regular expression like:
#\b[a-z]+\d[a-z]+\b#i
^ case insensitive
^^ a word boundary
^^^^^^ One or more letters
^^ One number
You can make it more restrictive by using {1,3} instead of + for the letters so that you have a sequence of 1 to 3 letters.
The complete expression would be something like:
$success = preg_match('#\b[a-z]+\d[a-z]+\b#i', $input_string, $matches);
where $matches[0] will contain the matched value, see the manual.

Filter array of numeric PIN code strings which may be in the format "######" or "### ###"

I have a PHP array of strings. The strings are supposed to represent PIN codes which are of 6 digits like:
560095
Having a space after the first 3 digits is also considered valid e.g. 560 095.
Not all array elements are valid. I want to filter out all invalid PIN codes.
Yes you can make use of regex for this.
PHP has a function called preg_grep to which you pass your regular expression and it returns a new array with entries from the input array that match the pattern.
$new_array = preg_grep('/^\d{3} ?\d{3}$/',$array);
Explanation of the regex:
^ - Start anchor
\d{3} - 3 digits. Same as [0-9][0-9][0-9]
? - optional space (there is a space before ?)
If you want to allow any number of any whitespace between the groups
you can use \s* instead
\d{3} - 3 digits
$ - End anchor
Yes, you can use a regular expression to make sure there are 6 digits with or without a space.
A neat tool for playing with regular expressions is RegExr... here's what RegEx I came up with:
^[0-9]{3}\s?[0-9]{3}$
It matches the beginning of the string ^, then any three numbers [0-9]{3} followed by an optional space \s? followed by another three numbers [0-9]{3}, followed by the end of the string $.
Passing the array into the PHP function preg_grep along with the Regex will return a new array with only matching indeces.
If you just want to iterate over the valid responses (loop over them), you could always use a RegexIterator:
$regex = '/^\d{3}\s?\d{3}$/';
$it = new RegexIterator(new ArrayIterator($array), $regex);
foreach ($it as $valid) {
//Only matching items will be looped over, non-matching will be skipped
}
It has the benefit of not copying the entire array (it computes the next one when you want it). So it's much more memory efficient than doing something with preg_grep for large arrays. But it also will be slower if you iterate multiple times (but for a single iteration it should be faster due to the memory usage).
If you want to get an array of the valid PIN codes, use codaddict's answer.
You could also, at the same time as filtering only valid PINs, remove the optional space character so that all PINs become 6 digits by using preg_filter:
$new_array = preg_filter('/^(\d{3}) ?(\d{3})$/D', '$1$2', $array);
The best answer might depend on your situation, but if you wanted to do a simple and low cost check first...
$item = str_replace( " ", "", $var );
if ( strlen( $item ) !== 6 ){
echo 'fail early';
}
Following that, you could equally go on and do some type checking - as long as valid numbers did not start with a 0 in which case is might be more difficult.
If you don't fail early, then go on with the regex solutions already posted.

Categories