PHP RegEx to allow mailto: http:// and tel: hyperlinks - php

What I need to do is allow a text field to validate and allow either a mailto: http:// or a tel: type of URL.
I'm using PHP 5 (and Laravel 4, but not as relevant to this post).
I've been googling for a while, but I can't seem to get an expression to allow a match for all three types. I've tried some long, complicated strings, and some real short ones and it just returns false.
Here's my latest:
mailto:([^\?]*)|http:([^\?]*)|tel:([^\?]*)
SOLUTION:
Since I'm using Laravel 4, I decided to use the parse_url function instead of a regex. That said, there were some other great solutions provided as well.
My final validator function:
Validator::extend('any_url', function($attribute, $value)
{
$allowed = ['mailto', 'http', 'https', 'tel'];
$parsed = parse_url($value);
return in_array($parsed['scheme'], $allowed);
});

You can use parse_url which will give you the scheme. Then check if it is within the ['mailto', 'http', 'https','tel']

Try this:
((mailto:\w+)|(tel:\w+)|(http://\w+)).+
http://regexr.com/3ar2c

You need to put whole of your regexes within a capture grouping,also you need // after http::
mailto:([^\?]*)|(http://([^\?]*))|(tel:([^\?]*))
Because in your regex the pip works different :
mailto: #first
([^\?]*)|http: #second
([^\?]*)|tel: #third
([^\?]*) #fourth

You probably need this:
/^((?:tel|https?|mailto):.*?)$/
Example:
$strings = array("http://www.me.com", "mailto:hey#there.nyc", "tel:951261412", "hyyy://www.me.com");
foreach($strings as $string){
if (preg_match('/^((?:tel|https?|mailto):.*?)$/im', $string)) {
echo $string ."\n";
}else{
echo "No Match for : $string \n";
}
}
DEMO PHP
DEMO REGEX
EXPLANATION:
^((?:tel|https?|mailto):.*?)$
-----------------------------
Assert position at the beginning of a line (at beginning of the string or after a line break character) (line feed) «^»
Match the regex below and capture its match into backreference number 1 «((?:tel|https?|mailto):.*?)»
Match the regular expression below «(?:tel|https?|mailto)»
Match this alternative (attempting the next alternative only if this one fails) «tel»
Match the character string “tel” literally (case insensitive) «tel»
Or match this alternative (attempting the next alternative only if this one fails) «https?»
Match the character string “http” literally (case insensitive) «http»
Match the character “s” literally (case insensitive) «s?»
Between zero and one times, as many times as possible, giving back as needed (greedy) «?»
Or match this alternative (the entire group fails if this one fails to match) «mailto»
Match the character string “mailto” literally (case insensitive) «mailto»
Match the character “:” literally «:»
Match any single character that is NOT a line break character (line feed) «.*?»
Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
Assert position at the end of a line (at the end of the string or before a line break character) (line feed) «$»

Related

Php regex that matches substring followed by any length of character and then comma

I have a long string containing Copyright: 'any length of unknown string here',
what regex should I write to exactly match this as substring in a string?
I tried this preg_replace('/Copyright:(.*?)/', 'mytext', $str); but its not working, it only matches the Copyright:
A lazily quantified pattern at the end of the pattern will always match no text in case of *? and 1 char only in case of +?, i.e. will match as few chars as possible to return a valid match.
You need to make sure you get to the ', by putting them into the pattern:
'/Copyright:.*?\',/'
^^^
See the regex demo
The ? in your group 1 (.*?) makes this block lazy, i.e. matching as few characters as possible. Removing that would solve it.
Copyright:(.*)',
However, that would match everything in that same line. If you have text in that same line, make sure to limit it further. My screenshot below just just grouping () to make it easier for you to look, you can do without the parentheses.
I usually use Regxr.com to test my regular expression, there's also many other similar tools online, note that this one is great in UX, but does not support lookbehind.

PHP regular expressions to filter results

I have a list of several email addresses which look like the following
smtp:email1#myemail.com
smtp:email2#something.myemail.com
SMTP:email3#myemail.com
X400: //some random line
Is there any way I can only get the emails which only end in myemail.com? So from the above, this would be
email1#myemail.com
email3#myemail.com
So it should get rid of any random lines, and it should also ignore it if there is anything else in the string e.g. something.
I have managed to get some data by doing
([a-zA-Z]+)(#)
Probably not the best way but it gets me whats infront of the # sign. Any help filtering these out appreciated.
Thanks
You may want to use a regex to filter only emails from domain myemail.com:
<?php
$emailList = <<< LOL
smtp:email1#myemail.com
smtp:email2#something.myemail.com
SMTP:email3#myemail.com
X400: //some random line
LOL;
preg_match_all('/smtp:(.*?#myemail\.com)$/im', $emailList , $matches, PREG_PATTERN_ORDER);
print_r($matches[1]);
/*
Array
(
[0] => email1#myemail.com
[1] => email3#myemail.com
)
*/
Demo:
http://ideone.com/hcd0aa
Regex Explanation:
smtp:(.*?#myemail\.com)$
Options: Case insensitive; Exact spacing; Dot doesn’t match line breaks; ^$ don’t match at line breaks; Greedy quantifiers
Match the character string “smtp:” literally «smtp:»
Match the regex below and capture its match into backreference number 1 «(.*?#myemail\.com)»
Match any single character that is NOT a line break character «.*?»
Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
Match the character string “#myemail” literally «#myemail»
Match the character “.” literally «\.»
Match the character string “com” literally «com»
Assert position at the end of the string, or before the line break at the end of the string, if any «$»

preg_match from some html code

How would I write a php preg_match() in php to pick out the 250 value. I have a large string of html code that I want to pick the 250 out of and I can't seem to get the regular expression right.
This is the html pattern I want to match - note that I want to extract the integer where the 250 is:
<span class="price-ld">H$250</span>
I have been trying for hours to do this and I can't get it to work lol
preg_match('/<span class="price-ld">H$(\d+)<\/span>/i', $your_html, $matches);
print "Its ".$matches[1]." USD";
The regex actually depends on your code. Where are you exactly searching for?
This is the regex you're looking for:
(?<=<span class="price-ld">H\$)\d+(?=</span>)
You can see the results here.
And here's the explanation:
Options: case insensitive; ^ and $ match at line breaks
Assert that the regex below can be matched, with the match ending at this position (positive lookbehind) «(?<=<span class="price-ld">H\$)»
Match the characters “<span class="price-ld">H” literally «<span class="price-ld">H»
Match the character “$” literally «\$»
Match a single digit 0..9 «\d+»
Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=</span>)»
Match the characters “</span>” literally «span>»

Remove number from large string in specific position [PHP RegEx]

I have a large string (multiple lines) I need to find numbers in with regex. The position the number I need is always proceeded/follow by an exact order of characters so I can use non-capturing matches to pinpoint the exact number I need. I put together a regex to get this number but it refuses to work and I can't figure it out!
Below is a small bit of php code that I can't get to work showing the basic format of what i need
$sTestData = 'lak sjdhfklsjaf<?kjnsdfh461uihrfkjsn+%5Bmlknsadlfjncas dlk';
$sNumberStripRE = '/.*?(?:sjdhfklsjaf<\\?kjnsdfh)(\\d+)(?:uihrfkjsn\\+%5Bmlknsadlfjncas).*?/gim';
if (preg_match_all($sNumberStripRE, $sTestData, $aMatches))
{
var_dump($aMatches);
}
the number I need is 461 and the characters before/after the spaces on either side of this number are always the same
any help getting the above regex working would be great!
This link RegExr: My Reg Ex (to an online regex genereator and my regex) shows that it should work!
g is an invalid modifier, drop it.
Ideone Link
With regard to that link, which regular expression engine is it working from? Built in Flex, so probably the ActionScript RegExp engine. They are not all the same, each one varies.
You have a number of double-backslashes, they should probably be single in those strings.
$sTestData = 'lak sjdhfklsjaf<?kjnsdfh461uihrfkjsn+%5Bmlknsadlfjncas dlk';
$lDelim = ' sjdhfklsjaf<?kjnsdfh';
$rDelim = 'uihrfkjsn+%5Bmlknsadlfjncas ';
$start = strpos($sTestData, $lDelim) + strlen($lDelim);
$length = strpos($sTestData, $rDelim) - $start;
$number = substr($sTestData, $start, $length);
Using regex you can accomplish your goal with the following code:
$string='lak sjdhfklsjaf<?kjnsdfh461uihrfkjsn+%5Bmlknsadlfjncas dlk';
if (preg_match('/(sjdhfklsjaf<\?kjnsdfh)(\d+)(uihrfkjsn\+%5Bmlknsadlfjncas)/', $string, $num_array)) {
$aMatches = $num_array[2];
} else {
$aMatches = "";
}
echo $aMatches;
Explanation:
I declared a variable entitled $string and made it equal to the variable you initially presented. You indicated that the characters on either side of the numeric value of interest were always the same. I assigned the numerical value of interest to $aMatches by setting $aMatches equal to back reference 2. Using the parentheses in regex you will get 3 matches: backreference 1 which will contain the characters before the number, backreference 2 which will contain the numbers that you want, and backreference 3 which is the stuff after the number. I assigned $num_array as the variable name for those backreferences and the [2] indicates that it is the second backreference. So, $num_array[1] would contain the match in backreference 1 and $num_array[3] would contain the match in backreference 3.
Here is the explanation of my regular expression:
Match the regular expression below and capture its match into backreference number 1 «(sjdhfklsjaf<\?kjnsdfh)»
Match the characters “sjdhfklsjaf<” literally «sjdhfklsjaf<»
Match the character “?” literally «\?»
Match the characters “kjnsdfh” literally «kjnsdfh»
Match the regular expression below and capture its match into backreference number 2 «(\d+)»
Match a single digit 0..9 «\d+»
Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
Match the regular expression below and capture its match into backreference number 3 «(uihrfkjsn+%5Bmlknsadlfjncas)»
Match the characters “uihrfkjsn” literally «uihrfkjsn»
Match the character “+” literally «+»
Match the characters “%5Bmlknsadlfjncas” literally «%5Bmlknsadlfjncas»
Hope this helps and best of luck to you.
Steve

PHP regular expression for positive number with 0 or 2 decimal places

I am trying to use the following regular expression to check whether a string is a positive number with either zero decimal places, or 2:
^\d+(\.(\d{2}))?$
When I try to match this using preg_match, I get the error:
Warning: preg_match(): No ending delimiter '^' found in /Library/WebServer/Documents/lib/forms.php on line 862
What am I doing wrong?
The error is about delimiter missing that is / or #, etc, make sure that you wrap regex expression in delimiters:
if (preg_match('/^\d+(\.(\d{2}))?$/', $text))
{
// more code
return true;
}
Or:
if (preg_match('#^\d+(\.(\d{2}))?$#', $text))
{
// more code
return true;
}
For PHP's preg suite of functions, the regexes must be specified with a delimiter, such as /; for instance, /[a-z]/ will match any character from a to z. When you give it the string "^\\d+(.(\\d{2}))?$", it wants to treat the regex as \\d+(.(\\d{2}))?$, delimited by ^s, but it can't find the second ^. Thus, fixing that is as simple as "/^\\d+(.(\\d{2}))?$/" The other thing you need to fix is the .; that's a metacharacter which will match any non-newline character; for a literal period, you want \.. This gives you the regex "/^\d+(\.(\d{2}))?$/". Also, note that if you don't want a capturing group, you can use "/^\d+(?:\.(\d{2}))?$/", which will put the digits after the decimal point in $1 instead of $2.

Categories