TIL: Using fzf to search in command history

Armno P. 🇹🇭
2 min readJan 16, 2020

Today I learned how to do a fuzzy search in command history using fzf, and a bit about sed.

It is useful when I want to search for a specific command I ran before, but I don’t really remember what it was. For example,

$ docker-compose exec php artisan migrate --seed

With help of fzf, I can easily search through commands list in history and find what I want using the fuzzy search.

macOS sed and GNU sed

In the Examples page of fzf repo, there are examples of fh() functions that uses fzf to search in command history.

# https://github.com/junegunn/fzf/wiki/examples#command-history
# fh - repeat history
fh() {
print -z $( ([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s --tac | sed -r 's/ *[0-9]*\*? *//' | sed -r 's/\\/\\\\/g')
}

When I run fh function in the terminal, fzf works fine. I can do the search. But when I select a command I want, I got an error from sed.

sed: illegal option -- r
usage: sed script [-Ealn] [-i extension] [file ...]
sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]
sed: illegal option -- r
usage: sed script [-Ealn] [-i extension] [file ...]
sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]

I did some Google search, and found that sed on macOS is not the same with sed on Linux. That's why I don't have-r option in my sed as I'm using macOS Catalina.

To fix that, There are 2 options

  • Change -r option of sed to -E, which does the same thing - to intepret a regular expression. So the function above would be:
fh() {
print -z $( ([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s --tac | sed -E 's/ *[0-9]*\*? *//' | sed -E 's/\\/\\\\/g')
}
  • Or, install gnu-sed which has -r option, and replace sed with gsed instead.
$ brew install gnu-sedfh() {
print -z $( ([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s --tac | gsed -r 's/ *[0-9]*\*? *//' | gsed -r 's/\\/\\\\/g')
}

I go with the first option.

Finally, I add --height 50% option to fzf so it takes only half of the screen. I also rename the function to just h() to make it easier to remember. (" h for history")

h() {
print -z $( ([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s --tac --height "50%" | sed -E 's/ *[0-9]*\*? *//' | sed -E 's/\\/\\\\/g')
}

Originally published at https://armno.in.th on January 16, 2020.

--

--