Repete o último comando N vezes

7

Falta de escrever um loop, há uma maneira de repetir o último comando N vezes.

Por exemplo, posso repetir o último comando uma vez usando um double bang (!!), mas como repito isso 30 vezes?

    
por Tyler Durden 21.06.2017 / 14:33

5 respostas

9

Com zsh e desde que a última linha de comando tenha sido apenas um comando ou pipeline ou e-or list (por exemplo, echo x , echo x | tr x y , echo x && echo y , até comandos compostos como { x; y; } ou for / while loops mas não echo x; echo y ):

repeat 30 !!

Para repetir a linha de comando anterior, mesmo que contenha vários comandos, use:

repeat 30 do !!; done

Ou:

repeat 30 {!!}

Com bash e apenas para comandos simples (entre os exemplos acima, apenas o caso echo x ), você pode definir uma função auxiliar como:

repeat() {
  local n="$1"
  shift
  while ((n-- > 0)); do
    "$@"
  done
}

(e use repeat 30 !! como acima). Um efeito colateral é que, como o código estará sendo executado em uma função, ele verá diferentes "$@" , "$#" e coisas como typeset funcionarão de forma diferente, então você não pode fazer coisas como:

eval 'echo "$1"'
repeat 30 !!

Outra abordagem para emular zsh do repeat 30 {!!} seria declarar um alias como:

alias repeat='for i in $(seq'

(assumindo uma $IFS não modificada)

E, em seguida, use:

repeat 30); { !!; }
    
por 21.06.2017 / 14:45
6

O menor que eu posso encontrar é:

date # or whatever command
for i in {1..30}; do !!; done
    
por 21.06.2017 / 14:53
3

Uma abordagem poderia ser usar o editor de linhas para inserir !!; 30 vezes.

Como no editor de linha readline ( bash ) no modo vi :

!!;Escdd30p

O equivalente a emacs funciona com o editor de linha zsh , mas aparentemente não com bash ' readline . No entanto, você poderia usar macros readline kbd em vez disso, o que aparentemente pode ser repetido:

Defina a macro kbd como !!; :

Ctrl+X(!!;Ctrl+X)

Que mais tarde você pode invocar 30 vezes como:

Alt+3Alt+0Ctrl+Xe
    
por 21.06.2017 / 15:11
1

Isso é um pouco feio, mas:

 eval "'fc -ln -1';: "{1..10}\;

O espaço inicial não é estritamente necessário, mas é útil para suprimir a inserção do comando eval no histórico, se $HISTCONTROL contiver ignorespace (ou ignoreboth ).

Alternativamente:

eval "fc -s $((HISTCMD-2)) "{1..10}\;

E:

eval 'history -s '{1..10}';fc -s -2;'
    
por 21.06.2017 / 16:24
0

O comando seq faz parte do padrão * nix e, portanto, não depende do seu shell. Usando-o e a construção de loop do seu shell, você pode fazer coisas como esta:

for i in $(seq 30); do !!; done

ou

for i in 'seq 30'; do !!; done

    
por 22.06.2017 / 03:28