首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在文档或页面中查找DOI

在文档或页面中查找DOI
EN

Stack Overflow用户
提问于 2008-08-26 12:37:33
回答 7查看 12.7K关注 0票数 55

对于构成a reasonable identifier的内容,DOI系统基本上没有任何有用的限制。然而,能够从PDF、网页等中提取DOI对于引用信息等非常有用。

有没有一种可靠的方法可以在不使用“DOI:”前缀的情况下识别文本块中的doi?(任何语言都可以接受,最好使用正则表达式,并且必须避免误报)

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2012-04-26 06:35:53

好吧,我目前正在从自由格式文本中提取成千上万的DOIs,我意识到my previous approach有一些问题,即关于编码实体和尾随标点符号,所以我继续阅读the specification,这是我能想到的最好的。

DOI前缀应由目录指示符和注册者代码组成。这两个部分应用句号(句点)分隔。

目录指示器应为"10“。目录指示符将整个字符串集合(前缀和后缀)区分为解析系统内的数字对象标识符。

非常简单,初始\b阻止我们“匹配”一个不是以10.开头的"DOI“

代码语言:javascript
复制
$pattern = '\b(10[.]';

DOI前缀的第二个元素应为注册人代码。注册者代码是分配给注册者的唯一字符串。

此外,所有分配的注册人代码都是数字,长度至少为4位,因此:

代码语言:javascript
复制
$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]+)*/';

是不区分大小写的,可以包含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';

瞧,])\S)+)\b&input=This is a short DOI: 10.1000/123456. This is NOT a DOI: 4210.1000/123456. This is a long DOI: 10.1016.12.31/nature.S0735-1097(98)2000/12/31/34:7-7!!! 10.1007/978-3-642-28108-2_19 10.1007.10/978-3-642-28108-2_19 (fictitious example, see @Ju9OR comment) 10.1016/S0735-1097(98)00347-7 10.1579/0044-7447(2006)35\[89:RDUICP\]2.0.CO;2 Also, correctly discards some falsy (X|HT)ML stuff like: )">here is a demo

票数 61
EN

Stack Overflow用户

发布于 2018-01-30 22:41:44

CrossRef has a recommendation,他们成功地在99.3%的DOI上进行了测试(他们知道):

代码语言:javascript
复制
/^10.\d{4,9}/[-._;()/:A-Z0-9]+$/i
票数 18
EN

Stack Overflow用户

发布于 2008-08-27 09:04:37

@Silas的健全性检查是个好主意。然而,正则表达式并不能覆盖所有的DOIs。第一个元素必须(当前)为10,第二个元素必须(当前)为数字,但第三个元素几乎不受任何限制:

“合法字符是Unicode的合法图形字符。这特别不包括控制字符范围0x00-0x1F和0x80-0x9F...”

这才是真正的问题所在。在实践中,我从未见过空格的使用,但规范特别允许这样做。基本上,似乎没有一种明智的方法来检测DOI的结束。

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27910

复制
相关文章

相似问题

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