'Delete duplicate commands of zsh_history keeping last occurence

I'm trying to write a shell script that deletes duplicate commands from my zsh_history file. Having no real shell script experience and given my C background I wrote this monstrosity that seems to work (only on Mac though), but takes a couple of lifetimes to end:

#!/bin/sh

history=./.zsh_history
currentLines=$(grep -c '^' $history)
wordToBeSearched=""
currentWord=""
contrastor=0
searchdex=""

echo "Currently handling a grand total of: $currentLines lines. Please stand by..."
while (( $currentLines - $contrastor > 0 ))
do
    searchdex=1
    wordToBeSearched=$(awk "NR==$currentLines - $contrastor" $history | cut -d ";" -f 2)
    echo "$wordToBeSearched A BUSCAR"
    while (( $currentLines - $contrastor - $searchdex > 0 ))
    do
        currentWord=$(awk "NR==$currentLines - $contrastor - $searchdex" $history | cut -d ";" -f 2)
        echo $currentWord
        if test "$currentWord" == "$wordToBeSearched"
        then
            sed -i .bak "$((currentLines - $contrastor - $searchdex)) d" $history
            currentLines=$(grep -c '^' $history)
            echo "Line deleted. New number of lines: $currentLines"
            let "searchdex--"
        fi
        let "searchdex++"
    done
    let "contrastor++"
done

^THIS IS HORRIBLE CODE NOONE SHOULD USE^

I'm now looking for a less life-consuming approach using more shell-like conventions, mainly sed at this point. Thing is, zsh_history stores commands in a very specific way:

: 1652789298:0;man sed

Where the command itself is always preceded by ":0;". I'd like to find a way to delete duplicate commands while keeping the last occurrence of each command intact and in order.

Currently I'm at a point where I have a functional line that will delete strange lines that find their way into the file (newlines and such):

#sed -i '/^:/!d' $history

But that's about it. Not really sure how get the expression to look for into a sed without falling back into everlasting whiles or how to delete the duplicates while keeping the last-occurring command.



Solution 1:[1]

The zsh option hist_ignore_all_dups should do what you want. Just add setopt hist_ignore_all_dups to your zshrc.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 yut23