I recently had a curiosity about words in the dictionary that share both "pro-" and "con-" as a prefix. So, for example, procession/concession, produce/conduce, profess/confess, progress/congress, and so on. I'm basically looking for any words that match both ^pro(.+)$ and ^con(.+)$, where the content of the capture group is the same.

My initial caveman command was:

sed -nr 's/^con(.+)$/\1/Ip' /usr/share/dict/words | \
xargs -I SUFFIX -n1 grep -i '^proSUFFIX$' /usr/share/dict/words

It seems to work, outputting a full "con-" word as long as there exists a matching "pro-" word. Problem is, it's slooow. It invokes grep for every potential match, asking it to scan the whole dictionary each time. I could speed it up by making a temporary file that only has pro/con words in it, but it feels like there must be some efficient way to do this without writing a file.

Is there a tool in the GNU world that's well suited to this kind of intersection search?

  • Something like egrep '^(pro|con).*' /usr/share/dict/words might do the trick as a starting point, perhaps. You could then put the resultant list through a sed, awk, or grep meatgrinder that only keeps paired words.
    – DopeGhoti
    Jul 28, 2015 at 20:12
  • Aha! egrep '^(pro|con).* /usr/share/dict/words | sed 's/^...//' | sort | uniq -d will give you a list of all the word-bases that have both a pro and con prefix!
    – DopeGhoti
    Jul 28, 2015 at 20:17
  • uniq -d! very nice. Jul 28, 2015 at 20:17

3 Answers 3


From my earlier comment to the question itself:

egrep '^(pro|con).* /usr/share/dict/words | sed -nE 's/^(pro|con)(.*)/\2/p' | sort | uniq -d 

will give you a list of all the word-bases that have both a pro and con prefix:

The initial egrep grabs all the words with pro and con prefixes. We then use sed to strip off pro and con from the beginning of each word, sort the list, and then use uniq -d to show ony entries on the list that have duplicates.

  • 2
    The combination of grep and sed is rather unnecessary, as sed can do both steps in one: sed -nr 's/^(pro|con)(.*)/\2/p' | sort | uniq -d
    – Peter.O
    Jul 28, 2015 at 22:04
  • I'll update to reflect this - thanks for the tip! Keep in mind that it only works in GNU sed, and not BSD sed.
    – DopeGhoti
    Jul 28, 2015 at 23:26
  • 2
    replace -r with -E and it will work with both seds ... also, Peter meant you can drop egrep and use just sed Jul 28, 2015 at 23:32

This will print out the words without the pro|con prefix:

grep '^\(pro\|con\)' /usr/share/dict/words | cut -c 4- | sort | uniq -c | awk '$1 == 2 {print $2}'
  • I do like this, as it seems more extensible (for example, if it needed to be modified to match three or more prefixes).
    – smitelli
    Jul 28, 2015 at 20:25

In this particular case - sorted input, so all con... words are listed before pro... words - you could use awk to store the lines matching ^con in an array and when you reach the lines matching ^pro, replace pro with con and if the result is in array print the root word:

awk '/^con/{arr[$0]=$0}; /^pro/{c=gensub(/pro/, "con", 1)
if (c in arr) print substr(c, 4)}' /usr/share/dict/words

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .