Como usar argumentos do comando anterior?


287

Eu sei que Esc+ .fornece o último argumento do último comando.

Mas estou interessado no primeiro argumento do último comando. Existe uma ligação de chave para fazer isso?

Nas mesmas linhas, existe uma maneira genérica de obter o enésimo argumento do último comando? Eu sei que em um script, você pode usar $0, $1etc., mas estes não funcionam na linha de comando.

Além disso, o que dizer de iterar através do argumento 0 dos comandos anteriores, como podemos fazer com o último argumento pressionando continuamente Esc+ .?

Respostas:


284

Assim como M-.(meta-ponto ou esc-ponto ou alt-ponto) é a função de linha de leitura yank-last-arg, M-C-y(meta-controle-y ou esc-ctrl-y ou ctrl-alt-y) é a função de linha de leitura yank-nth-arg. Sem especificar n, ele puxa o primeiro argumento do comando anterior.

Para especificar um argumento, pressione Escape e um número ou mantenha pressionada a tecla Alt e pressione um número. Você pode fazer Alt- -para começar a especificar um número negativo, solte Alt e pressione o dígito (isso será contado a partir do final da lista de argumentos.

Exemplo:

Digite o seguinte comando

$ echo a b c d e f g
a b c d e f g

Agora, no próximo prompt, digite echo(com um espaço a seguir) e, em seguida,

Pressione Alt- Ctrl- ye você verá agora:

$ echo a

sem pressionar Enterainda, faça o seguinte

Pressione Alt- 3 Alt- Ctrl-y

Pressione Alt- - 2 Alt- Ctrl-y

Agora você verá:

$ echo ace

A propósito, você poderia colocar o jogo echoem linha selecionando o argumento 0:

Pressione Alt- 0 Alt- Ctrl-y

Editar:

Para responder à pergunta que você adicionou ao seu original:

Você pode pressionar Alt- 0e pressionar repetidamente Alt- .para percorrer os comandos anteriores (arg 0). Da mesma forma Alt- e -depois repetindo Alt- ., você pode percorrer os últimos penúltimos argumentos anteriores.

Se não houver argumento apropriado em uma linha específica da história, a campainha será tocada.

Se houver uma combinação específica usada com freqüência, você poderá definir uma macro para que uma tecla seja executada. Este exemplo lembrará o segundo argumento dos comandos anteriores pressionando Alt- Shift- Y. Você pode escolher qualquer pressionamento de tecla disponível que preferir, em vez deste. Você pode pressioná-lo repetidamente para percorrer os anteriores.

Para experimentar, insira a macro em um prompt do Bash:

bind '"\eY": "\e2\e."'

Para torná-lo persistente, adicione esta linha ao seu ~/.inputrcarquivo:

"\eY": "\e2\e."

Infelizmente, isso não parece funcionar para arg 0 ou números de argumentos negativos.


14
Ao procurar atalhos de teclado para bash / readline, eu gosto de correr bind -lpe observar as ligações atuais.
Chad Skeeters

1
@ChadSkeeters: E -s(novo no Bash 4) lista macros criadas usando -x.
Pausado até novo aviso.

Observe que você também pode usar o argumento de dígito M-.: Alt-3 Alt-Ctrl-ypor exemplo, é igual a manter Alte digitar 3.. Se você digitar 3.isso várias vezes sem liberar, Altpercorrerá os terceiros argumentos de suas linhas de comando anteriores.
Sobremesa

@dessert: digo isso no meu segundo parágrafo e depois mostro um exemplo.
Pausado até novo aviso.

@ChadSkeeters, obrigado pelo aviso de que haveria centenas de entradas! Ri muito.
jdk1.0

309

!$ obtém o último elemento do argumento anterior da linha de comandos.


115
!:3você recebe o terceiro #
Matt Dodge

108
! * recebe todos eles
wonton

75
!!recebe o último comando inteiro. Útil se você esqueceu de usar sudo.
Un3qual

43
!:1-2obtém todos os argumentos, exceto o último dos 3
Tyler Brock

5
Apenas uma palavra de aviso - se você usar argumentos combinados como echo foo{,bar} baz, o comando será gravado como impresso e se expandirá posteriormente. Com o exposto, o uso de echo !:1depois resolve para echo foo{,bar}e depois expande para #echo foo foobar
Sean

200

Para usar o primeiro argumento, você pode usar !^ou!:1

Exemplo:

$ echo a b c d e 
a b c d e
$ echo !^
echo a
a

$ echo a b c d e 
a b c d e
$ echo !:1
echo a
a

Como sua pergunta é sobre o uso de outros argumentos, aqui estão alguns úteis:

!^      first argument
!$      last argument
!*      all arguments
!:2     second argument

!:2-3   second to third arguments
!:2-$   second to last arguments
!:2*    second to last arguments
!:2-    second to next to last arguments

!:0     the command
!!      repeat the previous line

As quatro primeiras formas são usadas com mais frequência. O formulário !:2-é um tanto contra-intuitivo, pois não inclui o último argumento.


Existe uma maneira de obter o penúltimo item? ou seja, sair file3de mv file1 file2 file3 target/?
Charlie Harding

3
Gostei muito desta resposta e, apenas por uma questão de integridade, sugiro também adicionar uma linha informando sobre a sintaxe '! -2' que permite acessar o comando anterior ao anterior.
bbv 17/05/19

1
@bbv Além disso, para obter ainda mais detalhes, o comando '! 2', que permite acessar a segunda entrada no histórico (se ainda estiver disponível, dependendo das configurações do histórico). Útil se você exibir o número do histórico em cada prompt.
816-8055 22/11/19

53

Eu gostei tanto da resposta do @larsmans que tive que aprender mais. Adicionando esta resposta para ajudar outras pessoas a encontrar a seção da página de manual e saber o que procurar no Google:

$ man  -P 'less -p ^HISTORY\ EXPANSION' bash
<...>
Word Designators

Word designators are used to select desired words from the event.
A : separates the event specification from the word designator.
It may be omitted if the word designator begins with a ^, $, *, -,
or %.  Words are numbered from the beginning of the line, with the
first word being denoted by 0 (zero).  Words are inserted into the
current line separated by single spaces.

   0 (zero)
          The zeroth word.  For the shell, this is the command word.
   n      The nth word.
   ^      The first argument.  That is, word 1.
   $      The last argument.
   %      The word matched by the most recent ‘?string?’ search.
   x-y    A range of words; ‘-y abbreviates 0-y’.
   *      All of the words but the zeroth.
          This is a synonym for 1-$’.  
          It is not an error to use * if there is just one word in
          the event; the empty string is returned in that case.
   x*     Abbreviates x-$.
   x-     Abbreviates x-$ like x*, but omits the last word.

   If a word designator is supplied without an event
   specification, the previous command is used as the event.

18

! ^ pode ser o comando para o primeiro argumento. não tenho certeza se existe uma maneira de obter o enésimo.


7
é!: n como sugerido acima
Sergiu

Existe uma maneira de obter o n-ésimo último item, assim como !:n, mas contando do final ao invés do início?
Charlie Harding

14

Você também pode obter argumentos de qualquer comando em seu histórico!


$ echo a b c d e f g
a b c d e f g
$ echo build/libs/jenkins-utils-all-0.1.jar
build/libs/jenkins-utils-all-0.1.jar
$ history | tail -5
  601  echo build/libs/jenkins-utils-all-0.1.jar
  602  history | tail -10
  603  echo a b c d e f g
  604  echo build/libs/jenkins-utils-all-0.1.jar
  605  history | tail -5
$ echo !-3:4
echo d
d
$ echo !604:1
echo build/libs/jenkins-utils-all-0.1.jar
build/libs/jenkins-utils-all-0.1.jar


4

Testado no Ubuntu 18.04


Para inserir argumentos anteriores:

  • Alt+ .: insere o último argumento do último comando.
  • Alt+ #+ .: insere #nth último argumento do último comando.
  • Alt+ -, #, Alt+ ., Zsh: Alt + -+ #+ .: inserção #nth primeiro argumento do último comando.

No Linux, você pode repetir comandos para voltar ao histórico

Exemplo:

O último comando é:

mv foo bar
  • Alt+ 0+ .: insere o primeiro argumento do último comando =mv
  • Alt+ 2+ .: insere o último 2º argumento do último comando =foo
  • up, Ctrl+ w: último comando sem a última palavra =mv foo

Atalhos gerais

  • Ctrl+ w: remove a última palavra do cursor
  • Alt+ d: remove a próxima palavra do cursor
  • Ctrl+ k: corta tudo após o cursor
  • Ctrl+ u, zsh: Alt + w: corta tudo antes do cursor
  • zsh: Ctrl + u: corta todo o comando (no bash você pode combinar Ctrl+ u, Ctrl+ k)
  • Ctrl+ y: cole caracteres previamente cortados com Ctrl+ ue Ctrl+k
  • Ctrl+ _: desfaz a última edição (muito útil quando excede Ctrl+ w)
  • Ctrl+ left: move para a última palavra
  • Ctrl+ right: move para a próxima palavra
  • homeou Ctrl+ a: move para o início da linha
  • endou Ctrl+ e: move para o final da linha

Para percorrer os argumentos em um comando anterior

só funciona no zsh

execute ou adicione isso ao seu ~/.zshrc

autoload -Uz copy-earlier-word
zle -N copy-earlier-word
bindkey "^[:" copy-earlier-word

Agora use Alt+ .para voltar o quanto quiser e, em seguida, use Alt+ :para percorrer os argumentos

Supondo que o último comando seja

echo 1 2 3 4 5
  • Alt+ .:5
  • Alt+ .+ ::4
  • Alt+ .+ :+ ::3
  • Alt+ .+ :+ :+ ::2
  • Alt+ .+ :+ :+ :+ ::1
  • Alt+ .+ :+ :+ :+ :+ ::echo

fonte: https://stackoverflow.com/a/34861762/3163120

Para ver todos os atalhos disponíveis

  • bash: bind -lp
  • zsh: bindkey -L

Estou mantendo isso atualizado nesta lista https://gist.github.com/madacol/da38e42d7e45c2949a9f425cc20543e9


1
Alt .no Zsh no Mac está digitando 🤔
André Pena

1
Esc . funciona, mesmo que funcione apenas para o último. Você não pode continuar digitando para voltar no tempo. Talvez valha a pena atualizar a resposta. Muito obrigado.
André Pena

Você pode executar bindkey -Lno zsh para ver todos os atalhos vinculados, talvez ele ajude a identificar o problema ou até mesmo encontrar outros comandos úteis. No meu caso, por exemplo: a ligação Alt .é definida como bindkey "^[." insert-last-word. Ctrl L(para limpar a tela) -> bindkey "^L" clear-screen. Alt+Ctrl h-> bindkey "^[^H" backward-kill-word(o mesmo que Ctrl wpara remover última palavra)
Madacol

@ Madacol Eu também posso ver nas chaves de ligação a palavra cópia anterior como bindkey "^[^_" copy-prev-word
kikeenrique

3

Basicamente, ele é usado para puxar argumentos anteriores (de comando) .

Por exemplo, se o seguinte comando for emitido:

echo Hello, world how are you today?

então, Hello,será o primeiro argumento, e today?o sexto , esse é o último; ou seja, pode ser referenciado digitando:

Alt+6 Seguido por Ctrl-Alt-6


Ctrlé tradicionalmente denotado como um personagem chapéu ^anexado aos nomes de chaves, e Altcomo M-isso é M eta prefixo.

Portanto, o atalho acima pode ser redefinido ^Mypara puxar.


Além disso, há um atalho de substituição de chapéus na linha de comando:

echo Hello, world!

^Hello^Bye

Bye, world!

para substituir a primeira sequência correspondente do comando anterior , significando:

Hello, world! Hello, people!

^Hello^Bye

resultaria em:

Bye, world! Hello, people!

deixando a segunda partida ( hello) inalterada.

Nota: Não deixe espaço entre os chapéus ou a operação não funcionará.


O acima é apenas um atalho para:

!:s/Hello/Bye

a substituição no nível do evento (*) da primeira cadeia encontrada (correspondida) no comando anterior, enquanto o prefixo da primeira parte com a gopção se aplicará a toda a linha g globalmente :

echo Hello, world! Hello, people!

!:gs/Hello/Bye

Bye, world! Bye, people!

como geralmente sendo feito em outros comandos relacionados, tais como sed, vie em regex(expressão regular) - uma maneira Standart de pesquisa ( seqüência de jogo ).

Não, você não pode fazer !:sg/Hello/Byeou !:s/Hello/Bye/gaqui, essa é a sintaxe !


  • ! é para eventos; evento pode ser entendido como saída ou operação de comando realizada no histórico de comandos.

Isso é o que eu entendi usando-o sozinho e tentando fazer as coisas sozinho, a partir do que li de várias fontes, incluindo páginas de manual, blogs e fóruns.

Espero que possa lançar alguma luz sobre maneiras misteriosas de bash, o shell Bourne-Again (uma brincadeira no shshell, que é chamada de shell Bourne após o sobrenome de seu inventor), o que é o shell padrão em muitas distribuições, incluindo servidores ( sistemas operacionais de servidores ).



0

O método descrito no final da resposta aceita também funciona com o argumento zeroth para mim. Eu tenho estas linhas no meu ~/.inputrc:

"\en": "\e0\e."
"\em": "\e1\e."
"\e,": "\e2\e."

\e2\e.tem a vantagem de \e2\e\C-ypercorrer os comandos anteriores se for pressionado repetidamente em vez de inserir o segundo argumento do comando anterior várias vezes.

Para inserir todo o comando anterior, você pode digitar !!\e^. \e^é history-expand-line.


0

Se você estiver em um Mac, tenderá a obter caracteres estendidos com ctrl + letra. Eu tenho minha chave de opção de barra de direito de espaço definida como meta no meu terminal (iTerm2) configurado. Isso significa que eu uso a tecla para navegar por palavra e extrair parâmetros dos comandos anteriores.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.