对于构成a reasonable identifier的内容,DOI系统基本上没有任何有用的限制。然而,能够从PDF、网页等中提取DOI对于引用信息等非常有用。
有没有一种可靠的方法可以在不使用“DOI:”前缀的情况下识别文本块中的doi?(任何语言都可以接受,最好使用正则表达式,并且必须避免误报)
发布于 2012-04-26 06:35:53
好吧,我目前正在从自由格式文本中提取成千上万的DOIs,我意识到my previous approach有一些问题,即关于编码实体和尾随标点符号,所以我继续阅读the specification,这是我能想到的最好的。
DOI前缀应由目录指示符和注册者代码组成。这两个部分应用句号(句点)分隔。
目录指示器应为"10“。目录指示符将整个字符串集合(前缀和后缀)区分为解析系统内的数字对象标识符。
非常简单,初始\b阻止我们“匹配”一个不是以10.开头的"DOI“
$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]+)*/';
是不区分大小写的,可以包含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。
发布于 2018-01-30 22:41:44
CrossRef has a recommendation,他们成功地在99.3%的DOI上进行了测试(他们知道):
/^10.\d{4,9}/[-._;()/:A-Z0-9]+$/i发布于 2008-08-27 09:04:37
@Silas的健全性检查是个好主意。然而,正则表达式并不能覆盖所有的DOIs。第一个元素必须(当前)为10,第二个元素必须(当前)为数字,但第三个元素几乎不受任何限制:
“合法字符是Unicode的合法图形字符。这特别不包括控制字符范围0x00-0x1F和0x80-0x9F...”
这才是真正的问题所在。在实践中,我从未见过空格的使用,但规范特别允许这样做。基本上,似乎没有一种明智的方法来检测DOI的结束。
https://stackoverflow.com/questions/27910
复制相似问题