O que pode fazer com que um item seja excluído do meu histórico bash?

5

Uma vez por dia, vou me deparar com um problema quando pesquiso um item de histórico no bash. A manipulação desse item, às vezes, exclui a entrada do histórico e às vezes não.

Aqui está um caso disso acontecendo:

$ls foo
ls: No such file or directory

# (ctrl-r)ls foo(tab)
$ ls foo

# (ctrl-a)(ctrl-k)
$

# (ctrl-r)ls foo
# (no matches)

Qual é a explicação para o que está acontecendo aqui?

    
por Eric Hu 11.04.2015 / 20:52

1 resposta

9

Acho que o motivo desse comportamento é como o Bash lida com a modificação de linhas de histórico anteriores. Que comandos como previous-history ( C - p ) ou reverse-search-history ( C - r ) é buscar entradas do histórico anterior:

previous-history (C-p)
       Fetch the previous command from the history list, moving back in the list.

Quando a entrada do histórico anterior é buscada , ela é impressa como se tivesse sido digitada. Agora, você pode apenas modificá-lo, mas não executá-lo (como no seu exemplo) ou modificá-lo e executá-lo. Quando você o executa, invoca accept-line :

accept-line (Newline or Return)

    Accept the line regardless of where the cursor is. If this line is
    non-empty, add it to the history list according to the setting of
    the HISTCONTROL and HISTIGNORE variables. If this line is a
    modified history line, then restore the history line to its
    original state.

Depois de pressionar Return , a linha modificada será salva no histórico e a linha original será deixada intacta. Mas vamos pensar sobre o que acontece se você apenas modificar a linha buscada sem pressionar Return - ela é modificada, mas não executada, então accept-line não é invocado. O que acontece é que a linha do histórico original se torna modificada .

Para ver isso na prática, adicione essa linha ao seu ~/.inputrc e inicie o novo subshell:

set mark-modified-lines On

Agora vamos fazer o mesmo que no seu exemplo:

$ echo April # 0) press Return - 'accept-line' is called

# 1. press C-r and type 'April' and Tab - you will see this again because
#    'echo April' is in history:

$ echo April

# 2. now kill this line using C-k or C-u. C-r 'April' doesn't work anymore
#    because there is no 'echo April' in the history
# 3. DON'T PRESS RETURN HERE! Press Up arrow first a couple of times and
#    press Return to invoke a different command, it can be anything you had
#    in your history but just no Return here
# 4. now, see 'history', somewhere there you will see the empty string. It
#    may look a bit different depending on your HISTTIMEFORMAT but note
#    there is an asterisk next to the history line number and a command is
#    missing. It's missing because it has been modified and saved in 2).

$ history
(...)
  483* 2015-04-12 02:36:19

Como você notou no segundo comentário à sua pergunta, se você pressionasse Return em 2, você não modificaria o comando original inserido no ponto 0) e seria capaz de invocá-lo com C - r .

OK, percebo que isso pode ser um pouco confuso e difícil de entender à primeira vista. Volte se tiver alguma dúvida, vou tentar ser mais claro.

    
por 12.04.2015 / 03:47