Вопрос

А DOI система не накладывает практически никаких полезных ограничений на то, что представляет собой разумный идентификатор.Однако возможность извлекать DOI из PDF-файлов, веб-страниц и т. д.весьма полезен для информации о цитировании и т. д.

Есть ли надежный способ идентифицировать DOI в блоке текста, не принимая префикс «doi:»?(приемлем любой язык, предпочтительны регулярные выражения и необходимо избегать ложных срабатываний)

Это было полезно?

Решение

Хорошо, сейчас я извлекаю тысячи DOI из текста произвольной формы (XML) и понял, что мой предыдущий подход было несколько проблем, а именно с закодированными объектами и конечной пунктуацией, поэтому я продолжил чтение спецификация и это лучшее, что я мог придумать.


Префикс DOI должен состоять из индикатора каталога, за которым следует код регистрации.Эти два компонента должны быть разделены полной остановкой (период).

Индикатор каталога должен быть «10».Индикатор каталога различает весь набор строк символов (префикс и суффикс) в качестве идентификаторов цифровых объектов в системе разрешения.

Достаточно просто, начальный \b не позволяет нам «сопоставлять» «DOI», который не начинается с 10.:

$pattern = '\b(10[.]';

Вторым элементом префикса DOI является код регистранта.Код регистрации является уникальной строкой, назначенной регистранту.

Кроме того, все присвоенные коды регистранта являются цифровыми и имеют длину не менее 4 цифр, поэтому:

$pattern = '\b(10[.][0-9]{4,}';

Код регистрации может быть дополнительно разделен на подэлементы для административного удобства при желании.Каждому подразделению Кодекса-регистрации предшествует полная остановка.

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*';

Синтаксис DOI должен быть составлен из префикса DOI и суффикса DOI, разделенного прямой чертой.

Однако в этом нет абсолютной необходимости: в разделе 2.2.3 указано, что необычные суффиксальные системы могут использовать другие соглашения (например, 10.1000.123456 вместо 10.1000/123456), но давайте немного послабимся.

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/';

Имя doi нечувствительное и может включать любые печатные символы из законных графических символов Unicode.Суффикс doi должен состоять из строки символов любой длины, выбранной регистрантом.Каждый суффикс должен быть уникальным для элемента префикса, который предшествует ему.Уникальный суффикс может быть последовательным номером, или он может включать идентификатор, сгенерированный или на основе другой системы.

Вот здесь все сложнее: из всех обработанных мной DOI я увидел следующие символы (кроме [0-9a-zA-Z] конечно) в своих суффиксы: .-()/:- -- итак, хотя его и не существует, DOI 10.1016.12.31/nature.S0735-1097(98)2000/12/31/34:7-7 вполне правдоподобно.

Логичным выбором было бы использовать \S или [[:graph:]] PCRE POSIX, давайте сделаем это:

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/\S+'; // or
$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/[[:graph:]]+';

Теперь у нас есть трудная проблема: [[:graph:]] класс представляет собой супернабор [[:punct:]] класс, который включает символы, которые легко найти в свободном тексте или любом языке разметки: "'&<> среди других.

Давайте пока просто отфильтруем разметку, используя отрицательный просмотр:

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?!["&\'<>])\S)+'; // or
$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?!["&\'<>])[[:graph:]])+';

Вышеупомянутое должно охватывать закодированные объекты (&), кавычки атрибутов (["']) и открывать/закрывать теги ([<>]).

В отличие от языков разметки, в свободном тексте обычно не используются знаки препинания, если они не ограничены хотя бы одним пробелом. или ставится в конце предложения, например:

Это длинный DOI: 10.1016.12.31/nature.S0735-1097(98)2000/12/31/34:7-7!!!

Решение здесь — закрыть нашу группу захвата и установить другую границу слова:

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?!["&\'<>])\S)+)\b'; // or
$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?!["&\'<>])[[:graph:]])+)\b';

И вуаля, вот демо.

Другие советы

@Силас Проверка работоспособности - хорошая идея.Однако регулярное выражение не охватывает все DOI.Первый элемент должен (на данный момент) иметь значение 10, а второй элемент должен (на данный момент) быть числовым, но третий элемент практически не ограничен:

«Юридические символы — это допустимые графические символы Юникода.В частности, исключаются диапазоны управляющих символов 0x00-0x1F и 0x80-0x9F..."

и вот в чем настоящая проблема.На практике я никогда не видел использования пробелов, но спецификация специально допускает это.По сути, не существует разумного способа обнаружения конец DOI.

CrossRef имеет рекомендацию, что они успешно протестированы на 99,3% DOI:

/^10.\d{4,9}/[-._;()/:A-Z0-9]+$/i

Я уверен, что на данный момент это не очень полезно для ОП, но я решил опубликовать то, что пытаюсь, на случай, если кто-то вроде меня наткнется на это:

(10.(\d)+/(\S)+)

Это соответствует:«10-точечная косая черта, что угодно, кроме пробелов»

Но для моего использования (очистка HTML) это означало поиск ложных срабатываний, поэтому мне пришлось сопоставить приведенное выше, а также избавиться от кавычек и значений «больше/меньше»:

(10.(\d)+/([^(\s\>\"\<)])+)

Я все еще тестирую их, но пока чувствую надежду.

Вот что я делаю:

(10[.][0-9]{4,}[^\s"/<>]*/[^\s"<>]+)

И несколько допустимых крайних случаев, когда это не дает сбоев, но другие, похоже, работают:

Кроме того, корректно отбрасываются некоторые ложные вещи (X|HT)ML, например:

  • <geo coords="10.4515260,51.1656910"></geo>

Это действительно старый вопрос, на который есть ответ, но вот еще одна потенциальная замена.

\b10\.(\d+\.*)+[\/](([^\s\.])+\.*)+\b

При этом предполагается, что пробелы не являются частью DOI.

Не проверял это на ложные срабатывания, но, похоже, он способен найти все крайние случаи, упомянутые на этой странице.

Следующее регулярное выражение должно выполнить эту работу (синтаксис регулярного выражения Perl):

/(10\.\d+\/\d+)/

Вы можете провести дополнительную проверку работоспособности, открыв URL-адреса.

http://hdl.handle.net/<doi>

и

http://dx.doi.org/<doi>

где кандидат дои,

и проверяем, что вы: а) получили статус HTTP 200 OK и б) возвращенная страница не является страницей «DOI не найден» для службы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top