check two slashes in string - php

I have following sting. I wanted to know any string has two slashes or not.
$sting = "largeimg/fee0b04800e22590/myimage1.jpg";
I am trying to use the following PHP emthodl
if(preg_match("#^/([A-Za-z]|[0-9])/([A-Za-z]|[0-9]+)$#", $sting))
But it is not working properly. Please help me.

Here is how to do it in regex (see demo):
^([^/]*/){2}
Your code:
if(preg_match("#^([^/]*/){2}#", $sting)) {
// two slashes!
}
Explain Regex
^ # the beginning of the string
( # group and capture to \1 (2 times):
[^/]* # any character except: '/' (0 or more
# times (matching the most amount
# possible))
/ # '/'
){2} # end of \1 (NOTE: because you are using a
# quantifier on this capture, only the LAST
# repetition of the captured pattern will be
# stored in \1)

you could use substr_count(), do:
$sting = "largeimg/fee0b04800e22590/myimage1.jpg";
if(substr_count($sting, '/') == 2) { echo "has 2 slashes"; }

To check for 2 slashes you can use this regex:
preg_match('#/[^/]*/#', $sting)

Several other answers provide regular expressions that work but they do not explain why the expression in the question does not work. The expression is:
#^/([A-Za-z]|[0-9])/([A-Za-z]|[0-9]+)$#
The section ([A-Za-z]|[0-9]) is equivalent to ([A-Za-z0-9]). The extra + in the second similar section makes that part quite different. The + is of higher precedence than the |. Hence the section ([A-Za-z]|[0-9]+) is equivalent to ([A-Za-z]|([0-9]+)) (ignoring the difference between capturing and non-capturing brackets). The expression is interpreted as:
^ Start of string
/ The character '/'
([A-Za-z]|[0-9]) One alphanumeric
/ The character '/'
(
[A-Za-z] One alpha character
| or
[0-9]+ One or more digits
)
$ End of the string
This will only match strings where the first three characters are /, one alphanumeric, then /. Then the remainder of the string must be either one alpha or several digits. Thus these strings would be matched:
/a/b
/c/123
/4/d
/5/6
/7/890123456789
These strings would not be matched:
/aa/b
c/c/123
/44/d
/5/6a
/5/a6
/7/ee

Related

Match regular expression specific character quantities in any order

I need to match a series of strings that:
Contain at least 3 numbers
0 or more letters
0 or 1 - (not more)
0 or 1 \ (not more)
These characters can be in any position in the string.
The regular expression I have so far is:
([A-Z0-9]*[0-9]{3,}[\/]?[\-]?[0-9]*[A-Z]*)
This matches the following data in the following cases. The only one that does not match is the first one:
02ABU-D9435
013DFC
1123451
03323456782
ADS7124536768
03SDFA9433/0
03SDFA9433/
03SDFA9433/1
A41B03423523
O4AGFC4430
I think perhaps I am being too prescriptive about positioning. How can I update this regex to match all possibilities?
PHP PCRE
The following would not match:
01/01/2018 [multiple / or -]
AA-AA [no numbers]
Thanks
One option could be using lookaheads to assert 3 digits, not 2 backslashes and not 2 times a hyphen.
(?<!\S)(?=(?:[^\d\s]*\d){3})(?!(?:[^\s-]*-){2})(?!(?:[^\s\\]*\\){2})[A-Z0-9/\\-]+(?!\S)
About the pattern
(?<!\S) Assert what is on the left is not a non whitespace char
(?=(?:[^\d\s]*\d){3}) Assert wat is on the right is 3 times a whitespace char or digit
(?!(?:[^\s-]*-){2}) Assert what is on the right is not 2 times a whitespace char a hyphen
(?!(?:[^\s\\]*\\){2}) Assert what is on the right is not 2 times a whitespace char a backslash
[A-Z0-9/\\-]+ Match any of the listed 1+ times
(?!\S) Assert what is on the right is not a non whitespace char
Regex demo
Your patterns can be checked with positive/negative lookaheads anchored at the start of the string:
at least 3 digits -> find (not necessarily consecutive) 3 digits
no more than 1 '-' -> assert absence of (not necessarily consecutive) 2 '-' characters
no more than 1 '/' -> assert absence of (not necessarily consecutive) 2 '/' characters
0 or more letters -> no check needed.
If these conditions are met, any content is permitted.
The regex implementing this:
^(?=(([^0-9\r\n]*\d){3}))(?!(.*-){2})(?!(.*\/){2}).*$
Check out this Regex101 demo.
Remark
This solution assumes that each string tested resides on its own line, ie. not just being separated by whitespace.
In case the strings are separated by whitespace, choose the solution of user #TheFourthBird (which essentially is the same as this one but caters for the whitespace separation)
You can test the condition for both the hyphen and the slash into a same lookahead using a capture group and a backreference:
~\A(?!.*([-/]).*\1)(?:[A-Z/-]*\d){3,}[A-Z/-]*\z~
demo
detailled:
~ # using the tild as pattern delimiter avoids to escape all slashes in the pattern
\A # start of the string
(?! .* ([-/]) .* \1 ) # negative lookahead:
# check that there's no more than one hyphen and one slash
(?: [A-Z/-]* \d ){3,} # at least 3 digits
[A-Z/-]* # eventual other characters until the end of the string
\z # end of the string.
~
To better understand (if you are not familiar with): these three subpatterns start from the same position (in this case the beginning of the string):
\A
(?! .* ([-/]) .* \1 )
(?: [A-Z/-]* \d ){3,}
This is possible only because the two first are zero-width assertions that are simple tests and don't consume any character.

explanation of preg_replace function in PHP [duplicate]

This question already has an answer here:
Reference - What does this regex mean?
(1 answer)
Closed 7 years ago.
The preg_replace() function has so many possible values, like:
<?php
$patterns = array('/(19|20)(\d{2})-(\d{1,2})-(\d{1,2})/', '/^\s*{(\w+)}\s*=/');
$replace = array('\3/\4/\1\2', '$\1 =');
echo preg_replace($patterns, $replace, '{startDate} = 1999-5-27');
What does:
\3/\4/\1\2
And:
/(19|20)(\d{2})-(\d{1,2})-(\d{1,2})/','/^\s*{(\w+)}\s*=/
mean?
Is there any information available to help understand the meanings at one place? Any help or documents would be appreciated! Thanks in Advance.
Take a look at http://www.tutorialspoint.com/php/php_regular_expression.htm
\3 is the captured group 3
\4 is the captured group 4
...an so on...
\w means any word character.
\d means any digit.
\s means any white space.
+ means match the preceding pattern at least once or more.
* means match the preceding pattern 0 times or more.
{n,m} means match the preceding pattern at least n times to m times max.
{n} means match the preceding pattern exactly n times.
(n,} means match the preceding pattern at least n times or more.
(...) is a captured group.
So, the first thing to point out, is that we have an array of patterns ($patterns), and an array of replacements ($replace). Let's take each pattern and replacement and break it down:
Pattern:
/(19|20)(\d{2})-(\d{1,2})-(\d{1,2})/
Replacement:
\3/\4/\1\2
This takes a date and converts it from a YYYY-M-D format to a M/D/YYYY format. Let's break down it's components:
/ ... / # The starting and trailing slash mark the beginning and end of the expression.
(19|20) # Matches either 19 or 20, capturing the result as \1.
# \1 will be 19 or 20.
(\d{2}) # Matches any two digits (must be two digits), capturing the result as \2.
# \2 will be the two digits captured here.
- # Literal "-" character, not captured.
(\d{2}) # Either 1 or 2 digits, capturing the result as \3.
# \3 will be the one or two digits captured here.
- # Literal "-" character, not captured.
(\d{2}) # Either 1 or 2 digits, capturing the result as \4.
# \4 will be the one or two digits captured here.
This match is replaced by \3/\4/\1\2, which means:
\3 # The two digits captured in the 3rd set of `()`s, representing the month.
/ # A literal '/'.
\4 # The two digits captured in the 4rd set of `()`s, representing the day.
/ # A literal '/'.
\1 # Either '19' or '20'; the first two digits captured (first `()`s).
\2 # The two digits captured in the 2nd set of `()`s, representing the last two digits of the year.
Pattern:
/^\s*{(\w+)}\s*=/
Replacement:
$\1 =
This takes a variable name encoded as {variable} and converts it to $variable = <date>. Let's break it down:
/ ... / # The starting and trailing slash mark the beginning and end of the expression.
^ # Matches the beginning of the string, anchoring the match.
# If the following character isn't matched exactly at the beginning of the string, the expression won't match.
\s* # Any whitespace character. This can include spaces, tabs, etc.
# The '*' means "zero or more occurrences".
# So, the whitespace is optional, but there can be any amount of it at the beginning of the line.
{ # A literal '{' character.
(\w+) # Any 'word' character (a-z, A-Z, 0-9, _). This is captured in \1.
# \1 will be the text contained between the { and }, and is the only thing "captured" in this expression.
} # A literal '}' character.
\s* # Any whitespace character. This can include spaces, tabs, etc.
= # A literal '=' character.
This match is replaced by $\1 =, which means:
$ # A literal '$' character.
\1 # The text captured in the 1st and only set of `()`s, representing the variable name.
# A literal space.
= # A literal '=' character.
Lastly, I wanted to show you a couple of resources. The regex-format you're using is called "PCRE", or Perl-Compatible Regular Expressions. Here is a quick cheat-sheet on PCRE for PHP. Over the last few years, several tools have been popping up to help you visualize, explain, and test regular expressions. One is Regex 101 (just Google "regex tester" or "regex visualizer"). If you look here, this is an explanation of the first RegEx, and here is an explanation of the second. There are others as well, like Debuggex, Regex Tester, etc. But I find the detailed match breakdown on Regex 101 to be pretty useful.

Regular Expression for numbers unless all digits are identical

I need help to write a regular expression to match numbers which may be broken up into sections by spaces or dashes e.g:
606-606-606
606606606
123 456-789
However, matches should be rejected if all the digits of the number are identical (or if there are any other characters besides [0-9 -]):
111 111 111
111111111
123456789a
If spaces/dashes weren't allowed, the Regex would be simple:
/^(\d)(?!\1*$)\d*$/
But how would I allow dashes and spaces in the number?
EDIT
How would I allow also letters in the same regex (dashes and spaces shoud be still allowed) e.g:
aaaaa - it's not ok
aa-aaa-aaa-aaaaa - it's not OK
ababab - it's OK
ab-ab-ab - it's OK
This rule checks only numbers.
^(?!(?:(\d)\1+[ -]*)+$)\d[\d- ]+$
Desired results can be achieved by this Regular Expression:
^(?!(?:(\d)\1+[ -]*)+$)\d[\d- ]+$
Live demo
Explanations:
^ # Start of string
(?! # Negative Lookahead to check duplicate numbers
(?: # Non-capturing group
(\d) # Capture first digit
\1+ # More digits same as lately captured one
[ -]* # Any spaces and dashes between
)+ # One or more of what's captured up to now
$ # End of string
) # End of negative lookahead
\d # Start of match with a digit
[\d- ]+ # More than one digit/dash/space
$ # End of string
The theory behind this regex is to use a lookaround to check if string contains any duplicate numbers base on the first captured number. If we have no match in this lookaround, then match it.
Even if you can, i wonder if a regex is the right tool to solve this problem. Just imagine your fellow developers scratching their heads trying to understand your code, how much time do you grant them? Even worse, what if you need to alter the rules?
A small function with some comments could make them happy...
function checkNumberWithSpecialRequirements($number)
{
// ignore given set of characters
$cleanNumber = str_replace([' ', '-'], '', $number);
// handle empty string
if ($cleanNumber == '')
return false;
// check whether non-digit characters are inside
if (!ctype_digit($cleanNumber))
return false;
// check if a character differs from the first (not all equal)
for ($index = 1; $index < strlen($cleanNumber); $index++)
{
if ($cleanNumber[$index] != $cleanNumber[0])
return true;
}
return false;
}

RegEx to convert PHP variables into HTML echo snippets

PHP vars can be of the following formats and can contain letters numbers and underscores:
$var_1
$var_1[key_1]
$var_1['key_1']
$var_1["key_1"]
$var_1[key_1][key_2]
$var_1['key_1']['key_2']
$var_1["key_1"]["key_2"]
$var_1->property_1
$var_1->property_1->property_2
Array and object will never have more than 2 nested elements. Objects won't have methods (i.e. $var_1->method_1() is not needed).
I need a RegEx matching them all, or a minimum amount of several RegExes, that would convert them into HTML echo snippets in the following format:
<?=$1?>
Where $1 is the entire matched string. If possible to add constants to the same RegEx it would be just perfect:
CONST_1 into <?=CONST_1?>
This should do it for the given examples:
\$\w+(?:\[(["']|)\w+\1\]|->\w+){0,2}
Replace it with <?=$0?> (make sure to use 0, because 1 is the first capture and not the entire match). I did not include constants, because I think that is rather tricky (how do you know it's a constant and not a reserved keyword - include all keywords?).
Explanation of the regex:
\$ # literal $
\w+ # letters, digits, underscores
(?: # subpattern to match indexing or a member
\[ # literal [
(["']|) # a ', a " or nothing (capture it in group 1)
\w+ # letters, digits, underscores
\1 # the correct matching closing delimiter
\] # literal ]
| # or
-> # literal ->
\w+ # letters, digits, underscores
){0,2} # end of subpattern, repeat 0 to 2 times
Note that if you use this pattern within PHP, you might have to escape the '.

php regular expression for "|" and digits

I want know, what regular expression should I have for my string. My string can contains only "|" and digits.For example: "111|333|111|333". And string must begin from number. I am using this code, but he is ugly:
if (!preg_match('/\|d/', $ids)) {
$this->_redirect(ROOT_PATH . '/commission/payment/active');
}
Thank you in advance. Sorry for my english.
Looking at your example I assume you are looking for a regex to match string that begin and end with numbers and numbers are separated with |. If so you can use:
^\d+(?:\|\d+)*$
Explanation:
^ - Start anchor.
\d+ - One ore more digits, that is a number.
(? ) - Used for grouping.
\| - | is a regex meta char used for alternation,
to match a literal pipe, escape it.
* - Quantifier for zero or more.
$ - End anchor.
The regex is:
^\d[|\d]*$
^ - Start matching only from the beginning of the string
\d - Match a digit
[] - Define a class of possible matches. Match any of the following cases:
| - (inside a character class) Match the '|' character
\d - Match a digit
$ - End matching only from the beginning of the string
Note: Escaping the | is not necessary in this situation.
A string that contains only | or digits and begins with a digit is written as ^\d(\||\d)*$. That means: either \| (notice the escape!) or a digit, written as \d, multiple times.
The ^ and $ mean: from start to end, i.e. there’s no other character before or after that.
I think /^\d[\d\|]*$/ would work, however, if you always have three digits separated by bars, you need /^\d{3}(?:\|\d{3})*$/.
EDIT:
Finally, if you always have sequences of one or more number separated by bars, this will do: /^\d+(?:\|\d+)*$/.

Categories