首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ISBN-10和ISBN-13之间的正则表达式区分

ISBN-10和ISBN-13之间的正则表达式区分
EN

Stack Overflow用户
提问于 2012-12-31 07:30:36
回答 5查看 6.9K关注 0票数 21

我有一个If-else语句,它检查一个字符串以查看是否存在ISBN-10或ISBN-13 (图书ID)。

我面临的问题是ISBN-10校验,它发生在ISBN-13校验之前,ISBN-10校验将匹配任何包含10个或更多字符的字符,因此可能会将ISBN-13误认为ISBN-10。

这是代码。

代码语言:javascript
复制
$str = "ISBN:9780113411436";

if(preg_match("/\d{9}(?:\d|X)/", $str, $matches)){
   echo "ISBN-10 FOUND\n";  
   //isbn returned will be 9780113411
   return 0;
}

else if(preg_match("/\d{12}(?:\d|X)/", $str, $matches)){
   echo "ISBN-13 FOUND\n";
   //isbn returned will be 9780113411436
   return 1;
}

我如何确保我避免了这个问题?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-12-31 08:24:25

为此,您实际上只需要一个正则表达式。然后执行更有效的strlen()检查,看看哪一个匹配。以下内容将匹配字符串中的ISBN-10和ISBN-13值,可以使用或不使用连字符,前面可以有字符串ISBN:ISBN:(space)ISBN(space)

查找ISBN:

代码语言:javascript
复制
function findIsbn($str)
{
    $regex = '/\b(?:ISBN(?:: ?| ))?((?:97[89])?\d{9}[\dx])\b/i';

    if (preg_match($regex, str_replace('-', '', $str), $matches)) {
        return (10 === strlen($matches[1]))
            ? 1   // ISBN-10
            : 2;  // ISBN-13
    }
    return false; // No valid ISBN found
}

var_dump(findIsbn('ISBN:0-306-40615-2'));     // return 1
var_dump(findIsbn('0-306-40615-2'));          // return 1
var_dump(findIsbn('ISBN:0306406152'));        // return 1
var_dump(findIsbn('0306406152'));             // return 1
var_dump(findIsbn('ISBN:979-1-090-63607-1')); // return 2
var_dump(findIsbn('979-1-090-63607-1'));      // return 2
var_dump(findIsbn('ISBN:9791090636071'));     // return 2
var_dump(findIsbn('9791090636071'));          // return 2
var_dump(findIsbn('ISBN:97811'));             // return false

这将搜索提供的字符串,查看它是否包含可能的ISBN-10值(返回1)或ISBN-13值(返回2)。如果不是,它将返回false

请参阅上面的。

正在验证ISBN:

对于严格的验证,Wikipedia PHP For ISBN提供了一些针对ISBN-10ISBN-13article验证函数。下面是那些复制、整理和修改的示例,用于上述函数的略微修改版本。

将返回块更改为以下内容:

代码语言:javascript
复制
    return (10 === strlen($matches[1]))
        ? isValidIsbn10($matches[1])  // ISBN-10
        : isValidIsbn13($matches[1]); // ISBN-13

验证ISBN-10:

代码语言:javascript
复制
function isValidIsbn10($isbn)
{
    $check = 0;

    for ($i = 0; $i < 10; $i++) {
        if ('x' === strtolower($isbn[$i])) {
            $check += 10 * (10 - $i);
        } elseif (is_numeric($isbn[$i])) {
            $check += (int)$isbn[$i] * (10 - $i);
        } else {
            return false;
        }
    }

    return (0 === ($check % 11)) ? 1 : false;
}

验证ISBN-13:

代码语言:javascript
复制
function isValidIsbn13($isbn)
{
    $check = 0;

    for ($i = 0; $i < 13; $i += 2) {
        $check += (int)$isbn[$i];
    }

    for ($i = 1; $i < 12; $i += 2) {
        $check += 3 * $isbn[$i];
    }

    return (0 === ($check % 10)) ? 2 : false;
}

请参阅上面的。

票数 41
EN

Stack Overflow用户

发布于 2012-12-31 07:32:25

使用^$匹配字符串的开头和结尾。通过使用字符串分隔符,测试10位或13位代码的顺序将变得无关紧要。

10位数字

代码语言:javascript
复制
/^ISBN:(\d{9}(?:\d|X))$/

13位数字

代码语言:javascript
复制
/^ISBN:(\d{12}(?:\d|X))$/

注意:根据http://en.wikipedia.org/wiki/International_Standard_Book_Number的说法,似乎ISBN中也可以有-。但根据您使用的$str,在检查10位或13位数字之前,看起来您已经删除了连字符。

附加说明:由于ISBN的最后一位用作前几位的校验和,因此仅靠正则表达式无法验证ISBN是否有效。它只能检查10位或13位的格式。

代码语言:javascript
复制
$isbns = array(
  'ISBN:1234567890',       // 10-digit
  'ISBN:123456789X',       // 10-digit ending in X
  'ISBN:1234567890123',    // 13-digit
  'ISBN:123456789012X',    // 13-digit ending in X
  'ISBN:1234'              // invalid
);

function get_isbn($str) {
   if (preg_match('/^ISBN:(\d{9}(?:\d|X))$/', $str, $matches)) {
      echo "found 10-digit ISBN\n";
      return $matches[1];
   }
   elseif (preg_match('/^ISBN:(\d{12}(?:\d|X))$/', $str, $matches)) {
      echo "found 13-digit ISBN\n";
      return $matches[1];
   }
   else {
      echo "invalid ISBN\n";
      return null;
   }
}

foreach ($isbns as $str) {
   $isbn = get_isbn($str);
   echo $isbn."\n\n";
}

输出

代码语言:javascript
复制
found 10-digit ISBN
1234567890

found 10-digit ISBN
123456789X

found 13-digit ISBN
1234567890123

found 13-digit ISBN
123456789012X

invalid ISBN
票数 3
EN

Stack Overflow用户

发布于 2012-12-31 07:32:59

切换ISBN块的顺序,同时去掉if else中的所有空格、冒号和连字符:

代码语言:javascript
复制
//Replace all the fluff that some companies add to ISBNs
$str = preg_replace('/(\s+|:|-)/', '', $str);

if(preg_match("/^ISBN\d{12}(?:\d|X)$/", $str, $matches)){
   echo "ISBN-13 FOUND\n";
   //isbn returned will be 9780113411436
   return 1;
}

else if(preg_match("/^ISBN\d{9}(?:\d|X)$/", $str, $matches)){
   echo "ISBN-10 FOUND\n";  
   //isbn returned will be 9780113411
   return 0;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14095778

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档