6

I am using agrep to find similar spelling words, for example:

agrep -1 hack /usr/share/dict/words

But it returns too many words, so I also hope the length of the word is same as the keyword. How can I specify that?

2 Answers 2

5

Using 1 agrep

The key to using agrep is to recognize that you can control the cost for things like adding, substituting, and deleting characters. For insertion it's the -I switch. For deletion it's -D.

$ agrep -1 -I2 -D2 '^hack$' /usr/share/dict/words

Example

$ agrep -1 -I2 -D2 '^hack$' /usr/share/dict/words
back
cack
fack
haak
hack
haik
hank
hark
hask
hawk
heck
hick
hock
huck
Jack
jack
lack
Mack
mack
Pack
pack
rack
sack
tack
Wack
wack
yack
Zack
zack

Details

So if we set the cost of insertion 1 higher than the number of errors we're willing to tolerate, and do the same for the cost of deletions, we'll never insert or delete any characters, thus maintaining our length, which is the length of the pattern we're matching, hack, i.e. 4.

So in the above command we've set our margin of error at 1 (-1). We've set our cost of doing and insertion or a deletion to 2 (-I2 -D2). And we've guarded our results so that they only match strings that are whole words which begin and end with our pattern, (^hack$).

NOTE: The caret (^) means the beginning of the string, and the dollar sign ($) the end. These are called anchors.

Using 2 agreps

As an alternative you can also use 2 agreps.

$ agrep '^[a-zA-Z]{4}$' /usr/share/dict/words | agrep -1 'hack'

Example

$ agrep '^[a-zA-Z]{4}$' /usr/share/dict/words | agrep -1 'hack'
back
cack
Chac
Chak
dhak
fack
haak
hack
haik
hake
hako
haku
hank
hark
hask
hawk
heck
hick
hock
huck
Jack
jack
lack
Mack
mack
Pack
pack
rack
sack
Shak
tack
thak
Wack
wack
yack
Zack
zack

Details

The first agrep is tasked with finding the set of strings that are 4 characters in length. The second agrep reduces this set further to only strings matching your pattern of hack with a single error allowed.

5
  • Thanks. What does "^hack$" mean?
    – Tim
    Dec 21, 2013 at 2:33
  • It anchors the string making sure that it's the beginning and the end of the line.
    – slm
    Dec 21, 2013 at 2:36
  • but "ack" doesn't begin or end with "hack"?
    – Tim
    Dec 21, 2013 at 2:38
  • @Tim - yeah I'm just noticing that, investigating.
    – slm
    Dec 21, 2013 at 2:38
  • @Tim - see updates, figured it out!
    – slm
    Dec 21, 2013 at 3:21
1

I don't know how you could specify that to agrep However, you might be able to use the shell to solve your problem. For example, with bash. In the following: Set the variable keyword to hack Set the length of keyword into l Pass l into awk via a variable named limit, and specify that awk print records whose length (as determined by the awk built-in function length) is equal to limit

keyword=hack; l=${#keyword};
agrep -1 $keyword /usr/share/dict/words | awk -v limit=$l 'length == limit'
Jack
Mack
back
hack
hake
hank
hark
hawk
heck
hick
hock
jack
lack
pack
rack
sack
tack
yack
1
  • Thanks! can you explain "awk -v limit=$l 'length() == limit'"? Is length() a function? How does it know what its argument is?
    – Tim
    Dec 21, 2013 at 2:24

You must log in to answer this question.

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