PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

preg_quote> <preg_match_all
Last updated: Fri, 10 Oct 2008

view this page in

preg_match

(PHP 4, PHP 5)

preg_match正規表現によるマッチングを行う

説明

int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags [, int $offset ]]] )

pattern で指定した正規表現により subject を検索します。

パラメータ

pattern

検索するパターンを表す文字列。

subject

入力文字列。

matches

matches を指定した場合、検索結果が代入されます。 $matches[0] にはパターン全体にマッチしたテキストが代入され、 $matches[1] には 1 番目ののキャプチャ用サブパターンにマッチした 文字列が代入され、といったようになります。

flags

flags には以下のフラグを指定できます。

PREG_OFFSET_CAPTURE
このフラグを設定した場合、各マッチに対応する文字列のオフセットも返されます。 これにより、返り値は配列となり、配列の要素 0 はマッチした文字列、 要素 1は対象文字列中におけるマッチした文字列のオフセット値 となることに注意してください。

offset

通常、検索は対象文字列の先頭から開始されます。 オプションのパラメータ offset を使用して 検索の開始位置を (バイト単位で) 指定することも可能です。

注意: offset を用いるのと、 substr($subject, $offset)preg_match()の対象文字列として指定するのとは 等価ではありません。 これは、pattern には、 ^, $(?<=x) のような言明を含めることができるためです。 以下を比べてみてください。

<?php
$subject 
"abcdef";
$pattern '/^def/';
preg_match($pattern$subject$matchesPREG_OFFSET_CAPTURE3);
print_r($matches);
?>

上の例の出力は以下となります。

Array
(
)

一方、この例を見てください。

<?php
$subject 
"abcdef";
$pattern '/^def/';
preg_match($patternsubstr($subject,3), $matchesPREG_OFFSET_CAPTURE);
print_r($matches);
?>

出力は以下のようになります。

Array
(
    [0] => Array
        (
            [0] => def
            [1] => 0
        )

)

返り値

preg_match() は、pattern がマッチした回数を返します。つまり、0 回(マッチせず)または 1 回となります。 これは、最初にマッチした時点でpreg_match() は検索を止めるためです。逆にpreg_match_all()は、 subject の終わりまで検索を続けます。 preg_match() は、エラーが発生した場合にFALSEを返します。

変更履歴

バージョン 説明
4.3.3 パラメータ offset が追加されました。
4.3.0 フラグ PREG_OFFSET_CAPTURE が追加されました。
4.3.0 パラメータ flags が追加されました。

例1 文字列 "php" を探す

<?php
// パターンのデリミタの後の "i" は、大小文字を区別しない検索を示す
if (preg_match("/php/i""PHP is the web scripting language of choice.")) {
    echo 
"A match was found.";
} else {
    echo 
"A match was not found.";
}
?>

例2 単語 "web" を探す

<?php
/* パターン内の \b は単語の境界を示す。このため、独立した単語の
 *  "web"にのみマッチし、"webbing" や "cobweb" のような単語の一部にはマッチしない */
if (preg_match("/\bweb\b/i""PHP is the web scripting language of choice.")) {
    echo 
"A match was found.";
} else {
    echo 
"A match was not found.";
}

if (
preg_match("/\bweb\b/i""PHP is the website scripting language of choice.")) {
    echo 
"A match was found.";
} else {
    echo 
"A match was not found.";
}
?>

例3 URL からドメイン名を得る

<?php
// get host name from URL
preg_match('@^(?:http://)?([^/]+)@i',
    
"http://www.php.net/index.html"$matches);
$host $matches[1];

// get last two segments of host name
preg_match('/[^.]+\.[^.]+$/'$host$matches);
echo 
"domain name is: {$matches[0]}\n";
?>

上の例の出力は以下となります。

domain name is: php.net

例4 名前つきサブパターンの使用法

<?php

$str 
'foobar: 2008';

preg_match('/(?<name>\w+): (?<digit>\d+)/'$str$matches);

print_r($matches);

?>

上の例の出力は以下となります。

Array
(
    [0] => foobar: 2008
    [name] => foobar
    [1] => foobar
    [digit] => 2008
    [2] => 2008
)

注意

ヒント

ある文字列が他の文字列内に含まれているかどうかを調べるためだけに preg_match() を使うのは避けた方が良いでしょう。 strpos()strstr() 関数を 使う方が速くなります。



preg_quote> <preg_match_all
Last updated: Fri, 10 Oct 2008
 
add a note add a note User Contributed Notes
preg_match
Marc
06-Oct-2008 05:16
@ Steve Todorov:
Your regex will not only match 999.999... but also 9999.9999... etc.

I'd rather take this regex:

/^(1\d{0,2}|2(\d|[0-5]\d)?)\.(1\d{0,2}|2(\d|[0-5]\d)?)
\.(1\d{0,2}|2(\d|[0-5]\d)?)\.(1\d{0,2}|2(\d|[0-5]\d)?)$/

this should represent any ip (v4). At least it did in a small test here ;)
Steve Todorov
03-Oct-2008 10:23
While I was reading the preg_match documentation I didn't found how to match an IP..
Let's say you need to make a script that is working with ip/host and you want to show the hostname - not the IP.

Well this is the way to go:

<?php
/* This is an ip that is "GET"/"POST" from somewhere */
$ip = $_POST['ipOrHost'];

if(
preg_match('/(\d+).(\d+).(\d+).(\d+)/',$ip))
 
$host = gethostbyaddr($ip);
else
 
$host = gethostbyname($ip);

echo
$host;
?>

This is a really simple script made for beginners !
If you'd like you could add restriction to the numbers.
The code above will accept all kind of numbers and we know that IP address could be MAX 255.255.255.255 and the example accepts to 999.999.999.999.

Wish you luck!

Best wishes,
Steve
Ashus
13-Sep-2008 12:18
If you need to match specific wildcards in IP address, you can use this regexp:

<?php

$ip
= '10.1.66.22';
$cmp = '10.1.??.*';

$cnt = preg_match('/^'
    
.str_replace(
     array(
'\*','\?'),
     array(
'(.*?)','[0-9]'),
    
preg_quote($cmp)).'$/',
    
$ip);

echo
$cnt;

?>

where '?' is exactly one digit and '*' is any number of any characters. $cmp mask can be provided wild by user, $cnt equals (int) 1 on match or 0.
wjaspers4[at]gmail[dot]com
28-Aug-2008 11:55
I found this rather useful for testing mutliple strings when developing a regex pattern.
<?php
/**
 * Runs preg_match on an array of strings and returns a result set.
 * @author wjaspers4[at]gmail[dot]com
 * @param String $expr The expression to match against
 * @param Array $batch The array of strings to test.
 * @return Array
 */
function preg_match_batch( $expr, $batch=array() )
{
// create a placeholder for our results
   
$returnMe = array();

// for every string in our batch ...
   
foreach( $batch as $str )
    {
// test it, and dump our findings into $found
       
preg_match($expr, $str, $found);

// append our findings to the placeholder
       
$returnMe[$str] = $found;
    }

    return
$returnMe;
}
?>
seth36 at gmail dot com
10-Aug-2008 06:12
For validation of email addresses, Cal Henderson's RFC 822 and RFC 2822 is_valid_email() functions rule all:

http://code.iamcal.com/php/rfc822/
Dino Korah AT webroot DOT com
09-Jul-2008 08:11
preg_match and preg_replace_callback doesnt match up in the structure of the array that they fill-up for a match.
preg_match, as the example shows, supports named patterns, whereas preg_replace_callback doesnt seem to support it at all. It seem to ignore any named pattern matched.
Tim
09-Jul-2008 12:01
I made a mistake in my previous post. Mail addresses may of course only be "exotic" in their local parts, not in the domain part. Therefore, an exotic mail address would be "exotic#%$mail@domain.com".
Tim
08-Jul-2008 06:51
For those not so familiar with regex's, I post my algorithmic email validation routine. It can more easily be changed for individual needs than regex's. My function does NOT recognize exotic email addresses as allowed by RFC. (For example, info@exotic%&$#mail.com is a legal email address but not allowed by my function.)
-Tim

<?php
function email_is_valid($email) {
   if (
substr_count($email, '@') != 1)
      return
false;
   if (
$email{0} == '@')
      return
false;
   if (
substr_count($email, '.') < 1)
      return
false;
   if (
strpos($email, '..') !== false)
      return
false;
  
$length = strlen($email);
   for (
$i = 0; $i < $length; $i++) {
     
$c = $email{$i};
      if (
$c >= 'A' && $c <= 'Z')
         continue;
      if (
$c >= 'a' && $c <= 'z')
         continue;
      if (
$c >= '0' && $c <= '9')
         continue;
      if (
$c == '@' || $c == '.' || $c == '_' || $c == '-')
         continue;
      return
false;
   }
  
$TLD = array (
        
'COM',   'NET',
        
'ORG',   'MIL',
        
'EDU',   'GOV',
        
'BIZ',   'NAME',
        
'MOBI''INFO',
        
'AERO''JOBS',
        
'MUSEUM'
     
);
  
$tld = strtoupper(substr($email, strrpos($email, '.') + 1));
   if (
strlen($tld) != 2 && !in_array($tld, $TLD))
      return
false;
   return
true;
}
?>
mailinglist dot php at hydras-world dot com
04-Jul-2008 06:30
The regexp below thinks that the e-mail address:

'me@de.com' is invalid, which it is not.

'/^([a-z0-9])(([-a-z0-9._])*([a-z0-9]))*\@
([a-z0-9])([-a-z0-9_])+([a-z0-9])*
(\.([a-z0-9])([-a-z0-9_-])([a-z0-9])+)*$/i'

I modified it and it seems to work for me in my limited tests of it.

YMMV.
brferreira at grad dot ufsc dot br
26-Jun-2008 11:48
Paperweight, this pattern worked fine for me (even for intranet adresses, like "john@localhost"; and also for subdomain emails, like "john@foo.bar.com"):
'/([a-z0-9])([-a-z0-9._])+([a-z0-9])\@
([a-z0-9])([-a-z0-9_])+([a-z0-9])
(\.([a-z0-9])([-a-z0-9_-])([a-z0-9])+)*/i'

but, still, this won't replace the "activation link", that is the better way to check if an e-mail is valid or not.
jonathan dot lydall at gmail dot removethispart dot com
27-May-2008 04:50
Because making a truly correct email validation function is harder than one may think, consider using this one which comes with PHP through the filter_var function (http://www.php.net/manual/en/function.filter-var.php):

<?php
$email
= "someone@domain .local";

if(!
filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo
"E-mail is not valid";
} else {
    echo
"E-mail is valid";
}
?>
Norbert
06-May-2008 09:00
Debian way is:
dpkg-reconfigure locales
Georg
04-Apr-2008 06:36
In addition to reiner-keller's comment about Umlaute using setlocale (LC_ALL, 'de_DE');

To enable 'de_DE' on my Debian 4 machine I first had to:
- uncomment 'de_DE' in file /etc/locale.gen and afterwards
- run locale-gen from the shell

preg_quote> <preg_match_all
Last updated: Fri, 10 Oct 2008
 
 
show source | credits | sitemap | contact | advertising | mirror sites