Comment modifier la commande shell actuelle sans l'exécuter?

13

Il semble y avoir beaucoup d'informations sur la façon d'éditer et d'exécuter une commande à l'aide de votre éditeur en utilisant "edit-and-execute-command (Cx Ce)", mais ce que j'aimerais réaliser, c'est prendre la commande shell actuelle, appliquer certains filtrages (à l'aide d'un script), puis le renvoyer pour demander une approbation / des modifications manuelles supplémentaires avant l'exécution. Est-ce possible avec bash?

Piotr Mazurek
la source
Ce n'est pas la bonne réponse à la question, mais essayez d'utiliser le terminal ZSH au lieu du Bash natif. Il a l'auto-complétion, donc n'exécutez pas les commandes immédiatement. J'ai personnellement essayé ce scénario spécifique et il m'oblige toujours à appuyer sur Entrée chaque fois que je fais un edit-and-execute-command.
Praveen Premaratne
1
Le raccourci qui fonctionne pour moi est Escape+ V, mais il va quand même exécuter la commande. Donc, pour la solution de contournement, j'ajouterais echoà l'avant pour l'exécuter en imprimant la commande sur la console pour examen.
kenorb
2
pouvez-vous s'il vous plaît faire un exemple concret? Je ne comprends pas "appliquer certains filtrages (à l'aide d'un script), puis le renvoyer à l'invite".
Kent
3
@PraveenPremaratne: zsh n'est pas un terminal , c'est un shell .
Arkadiusz Drabczyk

Réponses:

7

Dernière mise à jour sur mon expérience

La partie 0"+y$ddde la cartographie suivante est vraiment quelque chose à laquelle vous devriez réfléchir attentivement et l'adapter à vos goûts / flux de travail / expérience.

Par exemple, très souvent, je me suis retrouvé avec plusieurs lignes dans le tampon, où je veux seulement exécuter celle sur laquelle se trouve le curseur; dans ce cas, je peux utiliser à la 0"+y$dd:%d<CR>place de 0"+y$dd.

Et ce n'est là qu'un des scénarios possibles.

Réponse finale pour ceux qui aiment vim

Réponse originale

J'ai souvent besoin de faire de même et je le fais comme suit. (J'utilise normalement le set -o viin bash, donc les points 1 et 2 suivants sont différents si vous utilisez set -o emacs, la valeur par défaut; sur la base de votre question, il semble que les points 1 et 2 sont unifiés en Ctrl+ xsuivi de Ctrl+ e, ce qui est plus difficile à taper, à mon humble avis .)

  1. frapper Escapepour être en mode normal,
  2. appuyez sur vpour entrer dans l'éditeur pour modifier la commande,
  3. éditez la commande comme je veux,

(C'est ici que vous posez la question.)

  1. frapper Escape0"+y$dd:wq,
    • Remarque: 0"+y$pas simplement "+yy, car ce dernier copierait également la nouvelle ligne, ce qui entraînerait l'exécution de la commande lors du collage dans la ligne de commande,
  2. collez le presse-papiers sur la ligne de commande
    • la façon de procéder dépend du terminal que vous utilisez, je suppose; Je frappe Ctrl+ Alt+ vdans URxvt.
  3. procéder à l'approbation / modification manuelle.

Il s'agit clairement d'une solution de contournement, consistant à copier la commande modifiée dans le presse-papiers avant de supprimer la commande entière, afin que rien ne soit exécuté à la sortie de l'éditeur; mais c'est le mieux que je puisse me procurer.

Mise à jour

Comme mon EDITOR(et VISUAL) est égal à vim, lorsque je modifie la commande, je la modifie dans vim.

À cet égard, j'ai remarqué que le tampon est nommé /tmp/bash-fc.random, où se randomtrouve une chaîne aléatoire alphanumérique à 6 caractères.

Cela donne de l'espace à de nombreuses possibilités, si vous l'utilisez vimcomme éditeur, car vous pouvez définir un mappage dans votre .vimrcpour exécuter la séquence entière Escape0"+y$dd:wq. Par exemple, une commande que vous utiliseriez rarement lors de la modification d'une ligne de commande est Leaderd; vous pouvez donc mettre le mapping suivant dans votre .vimrcfichier

au BufEnter /tmp/bash-fc.* nn <Leader>d 0"+y$dd:wq<CR>

de sorte que l'étape 4 de la recette ci-dessus devienne

  1. frappé EscapeLeaderd
Enrico Maria De Angelis
la source
Pour moi, c'est le meilleur moyen de modifier les commandes
A.Villegas
2

Ce n'est pas possible de faire cela dans Bash / readline mais c'est possible dans zsh en utilisant la edit-command-linecommande:

darkstar% autoload edit-command-line; zle -N edit-command-line
darkstar% bindkey "^X^E" edit-command-line

Maintenant, appuyez sur Control- x Control- epour ouvrir votre éditeur, modifier la ligne, quitter l'éditeur - vous verrez la ligne de commande mise à jour mais elle ne sera pas exécutée automatiquement.

Arkadiusz Drabczyk
la source
1

Maintenant que j'y pense, peut-être qu'une variation de ce que @kenorb a suggéré dans un commentaire est la meilleure solution (car il semble qu'aucune solution n'existe), si nous voulons nous en tenir bash.

Ce que vous pouvez faire, c'est ajouter un #(le caractère de commentaire dans bash) à la commande, plutôt que echo. Ensuite, lorsque vous quittez l'exitor, la commande sera inefficace, et vous n'aurez qu'à appuyer sur arrow up(ou k, si vous utilisez set -o vi), supprimer le #et confirmer.

Notez que cette stratégie n'ajoute que quelques touches, elle peut donc être assez efficace, selon votre niveau de frappe.

Enrico Maria De Angelis
la source
1

Ces pièces pourraient vous rapprocher:

a) remplacer la liaison normale pour la nouvelle ligne nouvelle ligne (ctrl-M) bind -x '"\C-M":date"

b) saisir la ligne actuelle de l'historique en utilisant !#

remplacez la date par le script que vous voulez.

c) éditer manuellement

d) si nécessaire, liez d'une manière ou d'une autre !!:pqui imprime la nouvelle commande à la ligne de commande mais ne l'exécute pas, vous permettant ainsi de la modifier manuellement.

e) en utilisant ctrl-J soumettre la commande modifiée plutôt qu'une nouvelle ligne

ou ils pourraient ne pas ...

ShpielMeister
la source
1

Il y a une option dans bash pour modifier la commande de l'historique sans l'exécuter. Je ne suis pas sûr qu'il soit possible d'utiliser un script pour cela, cela ne semble pas probable. Cependant, vous pouvez apporter des modifications à l'aide des modificateurs d'historique.

  1. Activer l'option histverify pour empêcher l'exécution de la commande modifiée
  2. Utiliser une chaîne de modificateurs pour changer la dernière commande
  3. Utilisation "!!" pour mettre votre résultat en ligne de commande pour l'édition finale

Voici à quoi ça ressemble:

$ shopt -s histverify
$ ls *.sh
script1.sh  script2.sh  script3.sh  script-return.sh
$ !!:s/*/script1/:p
ls script1.sh
$ !!:s/1/2/:p
ls script2.sh
$ !!
$ ls script2.sh
script2.sh
Maxim Norin
la source
1

Je voudrais vous indiquer le framework Composure pour Bash (je n'y suis pas affilié): https://github.com/erichs/composure

Il fournit draftet revisefonctions que le son comme ils pourraient aider à ce que vous essayez de faire. Voici une (longue) citation du fichier Lisez-moi du projet:

Composure vous aide en vous permettant de rédiger rapidement des fonctions de coque simples, en décomposant vos filtres à long tuyau et vos commandes complexes en morceaux lisibles et réutilisables.

Rédiger d'abord, poser des questions plus tard

Une fois que vous avez créé votre joyau d'une commande, ne le jetez pas! Utilisez-le draft ()et donnez-lui un bon nom. Cela stocke votre dernière commande en tant que fonction que vous pourrez réutiliser ultérieurement. Pensez-y comme un brouillon.

  $ cat servers.txt
  bashful: up
  doc: down

  up-arrow

  $ cat servers.txt | grep down
  doc: down

  $ draft finddown

  $ finddown | mail -s "down server(s)" admin@here.com

Révisez, révisez, révisez!

Maintenant que vous avez une fonction shell minimale, vous voudrez peut-être l'améliorer grâce au refactoring et à la révision. Utilisez la revise ()commande pour réviser votre fonction shell dans votre éditeur préféré.

  • généraliser des fonctions avec des paramètres d'entrée
  • ajouter ou supprimer des fonctionnalités
  • ajouter des métadonnées de support pour la documentation

    $ revise finddown
    finddown ()
    {
      about finds servers marked 'down' in text file
      group admin
      cat $1 | grep down
    }
    
    $ finddown servers.txt
    doc: down
nwinkler
la source
0

Cela ne semble pas possible avec un raccourci clavier, au moins:

$ bind -P | grep -e command -e edit
complete-command can be found on "\e!".
edit-and-execute-command can be found on "\C-x\C-e".
emacs-editing-mode is not bound to any keys
possible-command-completions can be found on "\C-x!".
vi-editing-mode is not bound to any keys
l0b0
la source