Intereting Posts
Заказ коллекции Doctrine на основе связанного объекта, когда невозможно использовать аннотацию @orderBy Есть ли способ отключить добавление свойств в класс из экземпляра класса? Невозможно создать абстрактный класс … в appDevDebugProjectContainer.php – Symfony2 Mysql – Как я могу выбирать строки по годам, если у меня есть только метка времени? Чешские символы, кодирующие PHP Как вызвать функции wordpress в пользовательском скрипте php Компиляция PHP в статическую двоичную Как установить $ {var_name} Удаление повторяющихся строк из нескольких (2) текстовых файлов в PHP Как рассчитать разницу между двумя днями как форматированную строку? PHP StdErr после Exec () Отправка электронной почты через SMTP Gmail с помощью PHP Что такое XML, и когда я должен его использовать? Внутренняя ошибка сервера (ошибка HTTP 500) после установки phpmyadmin в определенном домене Чат на основе Telegram на сайте на основе PHP: HOWTO?

regex, различающийся между ISBN-10 и ISBN-13

У меня есть инструкция If-else, которая проверяет строку, чтобы увидеть, есть ли ISBN-10 или ISBN-13 (идентификатор книги).

Проблема, с которой я сталкиваюсь, заключается в проверке 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; } 

Как я могу избежать этой проблемы?

Related of "regex, различающийся между ISBN-10 и ISBN-13"

Для этого вам действительно нужно только одно регулярное выражение. Затем выполните более эффективную проверку 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:

Для строгой проверки статья Википедии для ISBN имеет некоторые функции проверки PHP для ISBN-10 и ISBN-13 . Ниже приведены примеры, скопированные, переработанные и измененные для использования с слегка измененной версией вышеуказанной функции.

Измените блок возврата на это:

  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; } 

См. ДЕМО выше.

Используйте ^ и $ для соответствия началу и концу строки. Используя ограничители строк, порядок, в котором вы тестируете 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 

Поместите проверку ISBN-13 перед проверкой ISBN-10? Это предполагает, что вы хотите сопоставить их как часть любой строки, то есть (ваш пример имеет дополнительный «ISBN:» в начале, поэтому совпадение в любом месте строки, по-видимому, является требованием какого-то рода)

Переключите порядок блока if else , также удалите все пробелы, двоеточия и дефисы из вашего ISBN:

 //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; } 
 ISBN10_REGEX = /^(?:\d[\ |-]?){9}[\d|X]$/i ISBN13_REGEX = /^(?:\d[\ |-]?){13}$/i