Comprendre le point d'exclamation (!) Dans bash

108

j'ai utilisé

history | less

pour obtenir les lignes des commandes précédentes et des chiffres sur le côté gauche, j'ai trouvé la ligne que je voulais répéter (p. ex. 22) et

!22

à l'invite de commande et cela a fonctionné - en exécutant le jeu de commandes sur la ligne que je faisais à ce moment-là. Je ne peux pas comprendre où le point d'exclamation est utilisé, que représente-t-il en termes d'actions effectuées par bash et où l'utiliser. D'après la documentation, je ne vois pas d'explication «tangible».

Vass
la source
6
Cette réponse pourrait aider
Michael Mrozek
9
Pas une réponse à votre question, mais <ctrl> + R vous permettra de rechercher de manière interactive votre historique, puis de l'exécuter immédiatement si vous trouvez ce que vous cherchez.
Kasterma

Réponses:

145

!est une fonctionnalité apparue à l'origine dans le shell C , à l'époque où vous pouviez compter sur les terminaux pour disposer de touches de direction. Cela est particulièrement utile si vous ajoutez le numéro de commande actuel à l'invite ( PS1="\!$ ") afin de pouvoir regarder rapidement votre écran pour obtenir les numéros des commandes passées.

Maintenant que vous pouvez utiliser les touches fléchées et des choses comme Ctrl-Rrechercher dans l'historique des commandes, je ne vois pas beaucoup d'utilisation de la fonctionnalité.

Une variante de ce que vous pourriez toujours trouver utile est celle !!qui ré-exécute la commande précédente. En soi, je ne trouve !!Enterpas plus rapide que juste Enter, mais cela peut être utile lorsqu'il est combiné à une commande plus grande.

Exemple: une erreur de pilote commune sur les sudosystèmes de base consiste à oublier le sudopréfixe d'une commande nécessitant des privilèges supplémentaires. Un novice retape toute la commande. L'élève diligent édite la commande à partir de l'historique des commandes du shell. Celui éclairé tape sudo !!.

Bash vous permet de désactiver le !traitement dans le shell avec set +o histexpandou set +H. Vous pouvez le désactiver dans Zsh avec set -K.

Warren Young
la source
4
Je trouve que Ctrl-P Ctrl-J est assez rapide; plus rapide que Up Enter, au moins.
éphémence
24
Si vous voulez seulement exécuter la dernière commande, Up / Enter, ça va, mais si vous voulez y ajouter quelque chose (disons, vous avez oublié de sudo, ou quelque chose), alors vous pouvez le faire sudo !!, par exemple. Cela pourrait être un peu plus rapide que "Up / Ctrl-A (ou Home, si vous êtes assez chanceux) / sudo / space / enter". YMMV. :)
1
@AquariusPower: citez-le. Ou echo 'Hi!'ou echo "Hi!"ou echo Hi\!. Tous font la même chose.
Warren Young
1
setopt NO_BANG_HISTdans zsh pourrait être plus mémorable que -K.
Gregory
bravo au enlightened ones:) ne peux pas croire que j'ai seulement été un étudiant assidu pendant tout ce temps ...
Pedreiro Il y a
49

S'il n'y a pas de réponse plus longue ici, il y en a certainement une sur Super User, puisque j'en ai lu une récemment. Dans la page de manuel de bash, vous trouverez une énorme section intitulée HISTORY EXPANSION sur le sujet.

Vous pouvez faire un hôte entier plus que simplement exécuter la dernière commande, ou le numéro X. Vous pouvez faire des choses comme !catexécuter la dernière commande qui a commencé avec cat. Ou !?bash?:s/bash/csh/exécute la dernière commande contenant bashmais la remplace par csh.

Cry Havok
la source
3
Bien que ce ne soit pas directement une réponse à la question de OP, cela nécessite beaucoup plus de votes positifs. Tellement utile! Merci Havok.
Malvim
Euh, je devrais vraiment regarder dans la page de manuel avant de commencer à googler.
erikbwork
1
!!:s/bash/csh/exécute la dernière commande , puis remplace bash par csh, le cas échéant. Pas la dernière commande qui incluait bash. Ce serait !?bash?:s/bash/csh/ou peut!?bash?:s/%/csh/
cde
Ayant beaucoup utilisé Bash pendant plusieurs années, j'ai été choqué de constater que je n'avais jamais entendu parler de ce mot clé auparavant, et même si j'ai passé des heures à parcourir les manpages, cette fonctionnalité est incroyablement obscure. Merci de signaler la section pertinente - c’est le seul endroit de la documentation où l’on explique suffisamment la situation.
Steve Benner le
39

Beaucoup plus peut être fait avec !tels que:

  • exécuter une commande qui est tapée avant 3 commandes: !-3
  • exécuter une commande qui commence par !ls

et beaucoup plus. Voir 15 exemples d'expansion de l'historique Linux Bash à connaître

utilisateur379997
la source
Upvoted cela. Aucune des autres réponses n'avait aucune de ces astuces intelligentes.
Gergely Lukacsy
Upvoted parce que www.thegeekstuff.com est tout simplement une ressource fantastique et qu’il s’agit de l’un des rares articles sur Linux que je n’ai jamais vu auparavant. Très utile.
Steve Benner le
4

Un de mes amis m'a envoyé ceci:

Cela fait partie de la bibliothèque d'histoire GNU. En bash, il est utilisé pour réexécuter les commandes de votre historique. Si vous voulez être hardcore, grep pour history_expansion_char dans bash-4.1 / lib / readline / histexpand.c pour les détails de l’implémentation.

Vass
la source
3

Bien sûr, vous pouvez faire !!pour réutiliser la dernière commande dans le shell bash. Et puis, il faut !$réutiliser la dernière partie de votre dernière commande.

par exemple voir un fichier

less path/to/your/file.txt

Si vous voulez maintenant éditer le même fichier, vous pouvez utiliser !$pour obtenir uniquement le chemin du fichier depuis la dernière commande

vim !$
Teshan Shanuka J
la source
1
Ah, j'espérais trouver ça. Comment se comporte-t-il avec deux arguments?
Jonathan
Il ne vous reste plus qu'à réutiliser le dernier argument des deux. $touch f1 f2et puis $vim !$évaluera à$vim f2
Teshan Shanuka J