Grep matching lines but return matching key IDs in GnuPG output

Posted on

Problem :

Having this input:

rsa2048/C7927B82 2015-08-30
rsa2048/FB2D99F9 2015-08-30

I want grep to only return the key ID, for example: C7927B92. Using the pattern from Grep characters before and after match?, I used

grep -o -P 'rsa.{3,13}'

resulting in

rsa2048/FB2D99F9

How do I clean this up?

I want to find duplicate short key IDs. Next I take the grep list of short key IDs, and then sort then and test for duplicates with sort | uniq -d. However it does not work since it provides false duplicates.

gpg2 --list-keys | grep -o -P 'rsa.{3,13}' | sort | uniq -d
 rsa2048/2642B5CD
 rsa2048/DF6AA92A

Solution :

You missunderstood the regular expression syntax. rsa.{3,13} greps for strings starting with rsa, followed by 3 to 13 repetitions of any character (. is the wildcard character in regular expressions).

To grep for the key ID, use match groups. You cannot do this using a single grep statement, and either have to use two of them or switch to another tool, for example sed or look for other ways to solve the problem. Using GNU grep, which supports the -P parameter you already used for perl-style regular expressions, you can use lookahead and lookbehind to achieve what you’re trying to do:

echo 'rsa2048/2642B5CD' | grep -o -P '(?<=rsa2048/)[[:xdigit:]]{8}'

This is only one way to achieve the desired result, and there are lots of other possible ways. The one above is probably one of the cleanest, an alternative might be simply cutting of the ID:

echo 'rsa2048/2642B5CD' | grep -o -P 'rsa.{3,13}' | cut -d/ -f2

Anyway, for scripting purpose you should go for the colon-seperated output achieved with --with-colons, which is much better parseable. Following lists all keys, and then filters for public keys (starting at the beginning of each line using ^), without caring for the key’s validity, but filtering RSA keys (field 4, algorithm ID 1) of size 2048 bits and finally cuts out field 5, which contains the key ID.

gpg2 --with-colons --list-keys | grep '^pub:[[:alpha:]]:2048:1:' | cut -d: -f5

Leave a Reply

Your email address will not be published. Required fields are marked *