我有一个If-else语句,它检查一个字符串以查看是否存在ISBN-10或ISBN-13 (图书ID)。
我面临的问题是ISBN-10校验,它发生在ISBN-13校验之前,ISBN-10校验将匹配任何包含10个或更多字符的字符,因此可能会将ISBN-13误认为ISBN-10。
这是代码。
$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;
}我如何确保我避免了这个问题?
发布于 2012-12-31 08:24:25
为此,您实际上只需要一个正则表达式。然后执行更有效的strlen()检查,看看哪一个匹配。以下内容将匹配字符串中的ISBN-10和ISBN-13值,可以使用或不使用连字符,前面可以有字符串ISBN:、ISBN:(space)或ISBN(space)。
查找ISBN:
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-10和ISBN-13的article验证函数。下面是那些复制、整理和修改的示例,用于上述函数的略微修改版本。
将返回块更改为以下内容:
return (10 === strlen($matches[1]))
? isValidIsbn10($matches[1]) // ISBN-10
: isValidIsbn13($matches[1]); // ISBN-13验证ISBN-10:
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:
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;
}请参阅上面的。
发布于 2012-12-31 07:32:25
使用^和$匹配字符串的开头和结尾。通过使用字符串分隔符,测试10位或13位代码的顺序将变得无关紧要。
10位数字
/^ISBN:(\d{9}(?:\d|X))$/13位数字
/^ISBN:(\d{12}(?:\d|X))$/注意:根据http://en.wikipedia.org/wiki/International_Standard_Book_Number的说法,似乎ISBN中也可以有-。但根据您使用的$str,在检查10位或13位数字之前,看起来您已经删除了连字符。
附加说明:由于ISBN的最后一位用作前几位的校验和,因此仅靠正则表达式无法验证ISBN是否有效。它只能检查10位或13位的格式。
$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";
}输出
found 10-digit ISBN
1234567890
found 10-digit ISBN
123456789X
found 13-digit ISBN
1234567890123
found 13-digit ISBN
123456789012X
invalid ISBN发布于 2012-12-31 07:32:59
切换ISBN块的顺序,同时去掉if else中的所有空格、冒号和连字符:
//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;
}https://stackoverflow.com/questions/14095778
复制相似问题