Files

4.6 KiB

idnorm

The identifiers a bibliography is held together by, read and checked.

Part of catena.

What it does

A DOI arrives bare, as a URL, with a doi: prefix, with the full stop the sentence around it left behind, in whatever case the publisher felt like. All of those are one identifier. A catalogue that stores them as they arrived cannot tell, so the same paper is three records and none of them join up.

idnorm reads one out of whatever it is wrapped in and writes it in the form it should be stored and compared in.

When you would use it

  • Before storing a reference, so that two spellings of one DOI are one row.
  • Auditing a bibliography for identifiers that cannot be right — an ISBN and an ISSN carry a check digit, and a mistyped one fails it.
  • Pulling identifiers out of running text, where the surrounding sentence is attached to them.

Install

cargo install --git https://git.pumpin.online/funkpower/catena idnorm

Example

$ printf '10.1000/182\ndoi:10.1093/mind/LIX.236.433\n0028-0836\n978-0-306-40615-7\narXiv:2401.01234\n' | idnorm
{"v":1,"input":"10.1000/182","kind":"doi","id":"10.1000/182","checksum":null,"url":"https://doi.org/10.1000/182"}
{"v":1,"input":"doi:10.1093/mind/LIX.236.433","kind":"doi","id":"10.1093/mind/lix.236.433","checksum":null,"url":"https://doi.org/10.1093/mind/lix.236.433"}
{"v":1,"input":"0028-0836","kind":"issn","id":"0028-0836","checksum":true,"url":"https://portal.issn.org/resource/ISSN/0028-0836"}
{"v":1,"input":"978-0-306-40615-7","kind":"isbn","id":"9780306406157","checksum":true,"url":"https://openlibrary.org/isbn/9780306406157"}
{"v":1,"input":"arXiv:2401.01234","kind":"arxiv","id":"2401.01234","checksum":null,"url":"https://arxiv.org/abs/2401.01234"}

The ones that cannot be right:

idnorm refs.txt | jq -r 'select(.checksum == false) | .input'

What a line was not:

$ printf 'hello\n' | idnorm
idnorm: not an identifier: hello
$ echo $?
1

Options

Option Effect
--kind <doi|issn|isbn|arxiv> Read every line as this kind rather than whatever it looks like
--quiet Say nothing about the lines that are not identifiers
--man Write this page as a manual page, in roff

Exit codes

Code Meaning
0 Every line was an identifier
1 At least one was not
64 The command line was wrong
74 The file could not be read

What it can and cannot tell you

It can say a string is well formed. An ISBN and an ISSN carry a check digit, weighted by position, which catches one mistyped figure and two transposed ones. A DOI and an arXiv identifier carry no checksum at all, so for those checksum is null rather than true — there is nothing to check against, and saying true would claim more than is known.

It cannot say the work exists. That is a fact about the world rather than about the string, and the only way to learn it is to ask a register. bibfetch does that:

idnorm refs.txt | bibfetch | jq -r 'select(.found | not) | .id'

Those two together are what "validate against a catalogue" means, and they are two tools because one of them touches the network and the other must not.

The four kinds

DOI. A registrant prefix beginning 10. and a suffix the registrant chooses. Stored lowercased, because a DOI is case-insensitive and two catalogues will disagree about the case of one. Read out of running text, with the trailing full stop, comma or bracket the sentence left on it removed.

ISSN. Eight digits in two fours, the last a check digit that may be X for ten. Stored hyphenated.

ISBN. Ten or thirteen digits. Stored as digits, without the hyphens, since where a publisher puts them varies. Only where the line is the identifier and nothing else — an ISBN has no prefix announcing it, so a sentence with a thirteen-digit number in it would otherwise read as one.

arXiv. Both forms: 2401.01234 since 2007, and math.GT/0309136 before it. A version suffix is kept, because v2 names a particular revision and citing without one means the latest.

As a library

let found = idnorm::parse("https://doi.org/10.1000/182").expect("an identifier");
assert_eq!(found.kind, idnorm::Kind::Doi);
assert_eq!(found.id, "10.1000/182");

idnorm::doi, idnorm::issn and idnorm::arxiv read one kind each, and idnorm::issn::valid checks a serial number's check digit.

See also

  • bibfetch — what a register says about one.
  • bibclean — the rest of a catalogue record.