Jak edytować bieżące polecenie powłoki bez wykonywania go?

13

Wydaje się, że jest sporo informacji na temat edytowania i wykonywania poleceń za pomocą edytora za pomocą „edit-and-execute-command (Cx Ce)”, ale chciałbym uzyskać bieżące polecenie powłoki, zastosować pewne filtrowanie (za pomocą skryptu), a następnie zwróć go z prośbą o dalsze zatwierdzenie / ręczne zmiany przed wykonaniem. Czy to możliwe dzięki Bash?

Piotr Mazurek
źródło
To nie jest właściwa odpowiedź na pytanie, ale spróbuj użyć terminala ZSH zamiast natywnego Bash. Ma funkcję autouzupełniania, więc nie wykonuj poleceń od razu. Osobiście wypróbowałem ten konkretny scenariusz i zawsze wymaga ode mnie naciśnięcia klawisza Enter za każdym razem, gdy to robię edit-and-execute-command.
Praveen Premaratne
1
Skrót, który działa dla mnie to Escape+ V, ale nadal będzie wykonywać polecenie. Jeśli chodzi o obejście, dodam echoz przodu, aby go wykonać, wypisując polecenie do konsoli w celu sprawdzenia.
kenorb
2
czy możesz podać konkretny przykład? Nie rozumiem „zastosuj określone filtrowanie (za pomocą skryptu), a następnie zwróć go do monitu”.
Kent
3
@PraveenPremaratne: zsh nie jest terminalem , jest powłoką .
Arkadiusz Drabczyk

Odpowiedzi:

7

Najnowsza aktualizacja mojego doświadczenia

Część 0"+y$dd poniższego mapowania jest naprawdę czymś, o czym powinieneś dokładnie pomyśleć i dostosować ją do swojego gustu / przepływu pracy / doświadczenia.

Na przykład bardzo często zdarza mi się, że kończę z wieloma liniami w buforze, gdzie chcę tylko wykonać ten, na którym znajduje się kursor; w tym przypadku mogę użyć0"+y$dd:%d<CR> zamiast 0"+y$dd.

A to tylko jeden z możliwych scenariuszy.

Ostateczna odpowiedź dla tych, którzy lubią vim

Oryginalna odpowiedź

Często muszę zrobić to samo i robię to w następujący sposób. (Zwykle używam set -o viin bash, więc punkty 1 i 2 poniżej są różne, jeśli używasz set -o emacs, domyślnie; na podstawie twojego pytania wygląda na to, że punkty 1 i 2 są ujednolicone w Ctrl+, xa następnie Ctrl+ e, co jest trudniejsze do wpisania, imho .)

  1. trafienie Escape w tryb normalny,
  2. trafienie v aby wejść do edytora w celu edycji polecenia,
  3. edytuj polecenie tak jak lubię,

(To tutaj zadajesz pytanie.)

  1. trafienie Escape0"+y$dd:wq ,
    • Uwaga: 0"+y$nie tylko "+yydlatego, że ten ostatni skopiowałby również nowy wiersz, a to spowodowałoby wykonanie polecenia po wklejeniu go w wierszu polecenia,
  2. wklej schowek w linii poleceń
    • jak to zrobić, zależy od terminalu, którego używasz, tak myślę; Nacisnąłem Ctrl+ Alt+ vw URxvt.
  3. przejdź do zatwierdzenia / edycji ręcznej.

Oczywiście jest to tylko obejście polegające na skopiowaniu edytowanego polecenia do schowka przed usunięciem całego polecenia, dzięki czemu nic nie zostanie wykonane po wyjściu z edytora; jednak jest to najlepsze, co mogę dla siebie zdobyć.

Aktualizacja

Ponieważ moje EDITOR(i VISUAL) jest równe vim, kiedy edytuję polecenie, edytuję je w vim.

W związku z tym zauważyłem, że bufor ma nazwę /tmp/bash-fc.random, gdzie randomjest 6-znakowym alfanumerycznym ciągiem losowym.

Daje to miejsce na wiele możliwości, jeśli używasz go vimjako edytora, ponieważ możesz zdefiniować pewne mapowanie w .vimrccelu wykonania całej sekwencji Escape0"+y$dd:wq. Na przykład jednym poleceniem, którego rzadko używasz podczas edycji wiersza poleceń, jest Leaderd; dlatego możesz umieścić następujący mapping w swoim .vimrcpliku

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

tak więc krok 4 w powyższym przepisie staje się

  1. trafienie EscapeLeaderd
Enrico Maria De Angelis
źródło
Dla mnie jest to najlepszy sposób edytowania poleceń
A.Villegas
2

Nie można tego zrobić w Bash / readline, ale jest to możliwe w Zsh za pomocą edit-command-linepolecenia:

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

Teraz naciśnij Control- x Control- eaby otworzyć edytor, edytować linię, opuścić edytor - zobaczysz zaktualizowaną linię poleceń, ale nie zostanie ona wykonana automatycznie.

Arkadiusz Drabczyk
źródło
1

Teraz, gdy o tym myślę, być może wariant tego, co @kenorb zasugerował w komentarzu, jest najlepszym rozwiązaniem (ponieważ wydaje się, że nie ma rozwiązania), jeśli chcemy się trzymać bash .

Możesz zamiast tego wstawić #(znak komentarza bash) do polecenia echo. Następnie, gdy wyjdziesz z exitora, polecenie będzie nieskuteczne i będziesz musiał tylko nacisnąć arrow up(lub k, jeśli używasz set -o vi), usunąć# i potwierdzić.

Pamiętaj, że ta strategia dodaje tylko kilka naciśnięć klawiszy, więc może być dość wydajna, w zależności od poziomu pisania.

Enrico Maria De Angelis
źródło
1

Te elementy mogą cię przybliżyć:

a) zastąp normalne wiązanie nowego wiersza (ctrl-M) bind -x '"\C-M":date"

b) pobrać bieżącą linię z historii za pomocą !#

zamień datę na dowolny skrypt.

c) edytuj ręcznie

d) w razie potrzeby w jakiś sposób związać !!:p którym drukuje nowe polecenie do wiersza poleceń, ale go nie wykonuje, umożliwiając w ten sposób jego ręczną edycję.

e) za pomocą ctrl-J prześlij edytowane polecenie zamiast nowego wiersza

albo mogą nie ...

ShpielMeister
źródło
1

W bash istnieje opcja modyfikowania polecenia z historii bez jego wykonywania. Nie jestem pewien, czy można do tego użyć skryptu, nie wydaje się to prawdopodobne. Chociaż możesz wprowadzać modyfikacje za pomocą modyfikatorów historii.

  1. Włącz opcję histverify, aby zapobiec wykonaniu zmodyfikowanego polecenia
  2. Użyj łańcucha modyfikatorów, aby zmienić ostatnie polecenie
  3. Posługiwać się "!!" umieścić wynik w wierszu polecenia do ostatecznej edycji

Oto jak to wygląda:

$ 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
źródło
1

Chciałbym wskazać Ci środowisko Composure dla Bash (nie jestem z nim związany): https://github.com/erichs/composure

Zapewnia drafti revisefunkcje, które brzmią, jakby mogły pomóc w tym, co próbujesz zrobić. Oto (długi) cytat z pliku readme projektu:

Kompresja pomaga w szybkim szkicowaniu prostych funkcji powłoki, rozkładaniu długich filtrów rurowych i złożonych poleceń na czytelne i wielokrotnego użytku fragmenty.

Szkicuj najpierw, zadawaj pytania później

Kiedy już stworzysz swój klejnot polecenia, nie wyrzucaj go! Użyj draft ()i nadaj mu dobre imię. To przechowuje twoje ostatnie polecenie jako funkcję, której możesz później użyć ponownie. Pomyśl o tym jak o szorstkim szkicu.

  $ 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

Popraw, popraw, popraw!

Teraz, gdy masz minimalną funkcję powłoki, możesz chcieć ją ulepszyć poprzez refaktoryzację i rewizję. Użyj revise ()polecenia, aby zmienić funkcję powłoki w swoim ulubionym edytorze.

  • uogólnić funkcje za pomocą parametrów wejściowych
  • dodaj lub usuń funkcjonalność
  • dodaj wspierające metadane do dokumentacji

    $ revise finddown
    finddown ()
    {
      about finds servers marked 'down' in text file
      group admin
      cat $1 | grep down
    }
    
    $ finddown servers.txt
    doc: down
nwinkler
źródło
0

Nie wydaje się to możliwe przy pomocy skrótu klawiaturowego, przynajmniej:

$ 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
źródło