Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'd like to be able to use a tool like grep to extract an entire bibtex reference rather than just the matching line. For example, grep Smith mydatabase.bib would return lines that contain the word Smith. I'd like to have a command-line program that returned the entire bibtex reference that encloses the word Smith.

  • How can this be done on the command-line?

In particular, I'd be interested in whether there is a way of using sed or awk to perform the task?

share|improve this question
add comment

5 Answers 5

up vote 6 down vote accepted

bibtool --select {"Smith"} <file>.aux -o <file>.bib creates a new bibliography data file which has only entries with Smith.

bibtool should be part of your TeX distribution.

share|improve this answer
    
Thanks. For those interested bibtool '--select{"Smith"}' mydatabase.bib did what I wanted (i.e., send matches to standard out). It took me a little while to realise that on my shell I needed to enclose the --select{...} in single quotes. –  Jeromy Anglim Sep 17 '11 at 10:40
    
what kind of shell do you have? –  Herbert Sep 17 '11 at 12:09
    
bash on Ubuntu... –  Jeromy Anglim Sep 19 '11 at 5:30
add comment

The bib2bib command line tool provides pretty flexible and reliable ways to filter/extract bibtex entries according to certain criteria. This (little known) utility is part of the bibtex2html tool suite. (Note: you have to look for the PDF documentation, the HTML documentation does not discuss bib2bib!)

For instance, to extract all entries where Smith is an author, one just writes:

bib2bib -oc smith-citations -ob smith.bib -c 'author : "Smith"' mydatabase.bib

Multiple conditions can be grouped and combined with and/or/not, so you could extend the above query to include also references that mention Smith in the title, abstract, or whatever.

A big plus of bib2bib compared to "hand-crafted" awk/sed/grep solutions is that it deals very well with string constants, crossrefs and so on (you can either include all dependencies in the output file or let bib2bib expand them, so that the entries are self-contained).

share|improve this answer
add comment

This kind of thing is a complete nuisance to do properly with the standard textutils, because Bibtex is not properly specified and the tools are not good at processing files if they are not structured by line.

You can get something close to what you want using tr to convert bib items into lines and back again. E.g.:

<input.bib tr "@\n" "\n\0"|grep -a article|(tr "\n\0" "@\n")

will select all bib items with the word article in them.

Two issues:

  1. The way this handles @ is crufty: occurrences within entries will cause them to be split into two lines and the first @ will be dropped. This can be fixed, but it will make the scripts more complex.
  2. The lines between tr-conversions contain lots of \0 characters, which means that many textutils will either not handle them or will need to have switches passed to them: here grep needs the -a switch.

Postscript

The following function definitions perform a slightly more sophisticated conversion that handles @ better (and uses sed):

bib2unix () { if test $# > 0; then cat "$@"; else cat; fi | tr "@\n" "\n\0" | sed "2,\$s/^/@/"; }
unix2bib () { tr -d "\n" | tr "\0" "\n"; }

which can be used so:

bib2unix input.bib |grep -a @article| unix2bib

to select all articles and cat them to STDOUT.

share|improve this answer
add comment

If you do not need to process it further in an automated way (i.e., if you do not care about extra garbage), a quick and dirty solution is grep -10 Smith mydatabase.bib (the number is adjustable). This option (which appears to be a GNU extension) makes grep output not only the matching line, but also 10 lines of additional context on either side, which should be more than enough to contain the whole bibtex entry.

share|improve this answer
    
Could you please explain in more details what such a grep does? –  N.N. Sep 15 '11 at 11:21
1  
It searches the file for all lines containing "Smith", and outputs each together with 10 lines of leading and trailing context (the idea being that the bibtex entry fits within this context). This option seems to be a GNU extension. –  Emil Jeřábek Sep 15 '11 at 11:32
    
Cheers! I should've mentioned that it would more sense to add the details on the option to your answer (by editing it) instead of as a comment. –  N.N. Sep 15 '11 at 11:34
add comment

Although I prefer the dedicated tools such as bibtool and bib2bib, here is one way of doing the task with awk.

  • awk 'BEGIN {RS="\n@"} /Smith/{print "@" $0}' mydatabase.bib

    • The record separator \n@ works if the bibtex database is formatted neatly with @ always appearing in the first column.
    • {print "@' $0} is optional. It replaces the @ removed by making @ part of the record separator. This would be important if the bibtex records are being piped to another location.
  • awk -v RS='\n@' '/Smith/' mydatabase.bib

    • This an abbreviated version of similar to above
    • -v RS='\n@' sets the record separator variable on the command-line.
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.