Opravdu si užívám použití control+r
pro rekurzivní prohledávání historie mých příkazů. Našel jsem několik dobrých možností, které s ním rád používám:
# ignore duplicate commands, ignore commands starting with a space
export HISTCONTROL=erasedups:ignorespace
# keep the last 5000 entries
export HISTSIZE=5000
# append to the history instead of overwriting (good for multiple connections)
shopt -s histappend
Jediným problémem pro mě je, že erasedups
smaže pouze sekvenční duplikáty - takže s tímto řetězcem příkazů:
ls
cd ~
ls
Příkaz ls
bude skutečně zaznamenán dvakrát. Přemýšlel jsem o pravidelném běhu w/cron:
cat .bash_history | sort | uniq > temp.txt
mv temp.txt .bash_history
Tím by se dosáhlo odstranění duplikátů, ale bohužel by pořadí nebylo zachováno. Pokud soubor sort
nejprve neeviduji, nemyslím si, že uniq
může fungovat správně.
Jak mohu odstranit duplikáty z mého .bash_history, při zachování pořadí?
Existují nějaké problémy s přepsáním .bash_history
soubor skriptem? Pokud například odeberete soubor protokolu Apache, myslím, že musíte poslat signál Nohup/reset pomocí kill
, aby bylo možné vyprázdnit připojení k souboru. Pokud tomu tak je v případě .bash_history
soubor, možná bych mohl nějak použít ps
ke kontrole a ujistit se, že neexistují žádné připojené relace před spuštěním filtrovacího skriptu?
Tento příkaz funguje jako sort|uniq
, ale udržuje linky na místě
nl|sort -k 2|uniq -f 1|sort -n|cut -f 2
V zásadě připojí na každý řádek své číslo. Po sort|uniq
- jsou všechny řádky řazeny zpět podle jejich původního pořadí (pomocí pole číslo řádku) a číslo řádku je z řádků odstraněno.
Toto řešení má tu vadu, že není definováno, který zástupce třídy stejných řádků bude činit ve výstupu, a proto není definována jeho pozice v konečném výstupu. Pokud by však měl být vybrán nejnovější zástupce, můžete sort
vstup pomocí druhého klíče:
nl|sort -k2 -k 1,1nr|uniq -f1|sort -n|cut -f2
Pro přečtení a zapsání historie můžete použít history -a
a history -w
.
Takže jsem hledal stejnou přesnou věc poté, co jsem byl otráven duplikáty, a zjistil jsem, že když upravím svůj ~/.bash_profile (Mac) pomocí:
export HISTCONTROL=ignoreboth:erasedups
Dělá přesně to, co jste chtěli, udržuje pouze poslední příkaz. ignoreboth
je vlastně jako dělat ignorespace:ignoredups
a to spolu s erasedups
provede práci.
Alespoň na mém Mac terminálu s bashem to funguje perfektně. Nalezeno zde na askubuntu.com .
Našel jsem toto řešení ve volné přírodě a testoval:
awk '!x[$0]++'
Při prvním zobrazení konkrétní hodnoty řádku ($ 0) je hodnota x [$ 0] nula.
Hodnota nula je invertována s !
a stane se jedním.
Příkaz, který vyhodnocuje jeden způsobí výchozí akci, kterou je tisk.
Proto poprvé poprvé $0
je vidět, je vytištěno.
Pokaždé (opakuje se) hodnota x[$0]
byl zvýšen,
jeho negovaná hodnota je nula a příkaz, který vyhodnocuje na nulu, se nevytiskne.
Chcete-li zachovat poslední opakovanou hodnotu, obráťte historii a použijte stejný awk:
awk '!x[$0]++' ~/.bash_history # keep the first value repeated.
tac ~/.bash_history | awk '!x[$0]++' | tac # keep the last.
Rozšíření Claytonovy odpovědi:
tac $HISTFILE | awk '!x[$0]++' | tac | sponge $HISTFILE
tac
obrátí soubor, ujistěte se, že jste nainstalovali moreutils
, takže máte sponge
k dispozici, jinak použijte dočasný soubor.
Toto je starý příspěvek, ale trvalý problém pro uživatele, kteří chtějí mít otevřeno více terminálů a mít historii synchronizovanou mezi okny, ale ne duplikovanou.
Moje řešení v .bashrc:
shopt -s histappend
export HISTCONTROL=ignoreboth:erasedups
export Prompt_COMMAND="history -n; history -w; history -c; history -r"
tac "$HISTFILE" | awk '!x[$0]++' > /tmp/tmpfile &&
tac /tmp/tmpfile > "$HISTFILE"
rm /tmp/tmpfile
history -n
přečte všechny řádky z $ HISTFILE, které se mohly vyskytnout v jiném terminálu od posledního návratu vozíkuhistory -w
zapíše aktualizovanou vyrovnávací paměť do $ HISTFILEhistory -c
vymaže buffer, takže nedochází k duplicitěhistory -r
znovu přečte $ HISTFILE a připojí se k nyní prázdné vyrovnávací pamětitac
převrátí a poté převrátí zpět, aby mohl být uložen s nejnovějšími příkazy, které jsou v historii nejnovějšíPokaždé, když otevřete nový Shell, historie vymaže všechny dupy a pokaždé, když narazíte na Enter klíč v jiném okně prostředí/terminálu, aktualizuje tuto historii ze souboru.
Zachovaly by se poslední duplicitní řádky:
Ruby -i -e 'puts readlines.reverse.uniq.reverse' ~/.bash_history
tac ~/.bash_history | awk '!a[$0]++' | tac > t; mv t ~/.bash_history
Chcete-li jedinečně zaznamenat každý nový příkaz, je složité. Nejprve je třeba přidat do ~/.profile
Nebo podobně:
HISTCONTROL=erasedups
Prompt_COMMAND='history -w'
Pak je třeba přidat do ~/.bash_logout
:
history -a
history -w