Bagaimana cara saya mengedit perintah shell saat ini tanpa menjalankannya?

13

Tampaknya ada cukup banyak informasi tentang cara mengedit dan mengeksekusi perintah menggunakan editor Anda menggunakan "edit-dan-eksekusi-perintah (Cx Ce)", tetapi apa yang ingin saya capai adalah mengambil perintah shell saat ini, terapkan penyaringan tertentu (menggunakan skrip) dan kemudian mengembalikannya untuk meminta persetujuan / perubahan manual lebih lanjut sebelum eksekusi. Apakah ini mungkin dengan bash?

Piotr Mazurek
sumber
Ini bukan jawaban yang tepat untuk pertanyaan, tetapi coba gunakan terminal ZSH bukan Bash asli. Ini memiliki penyelesaian otomatis jadi jangan langsung menjalankan perintah. Saya pribadi telah mencoba skenario khusus ini dan selalu mengharuskan saya untuk menekan enter setiap kali saya melakukan edit-and-execute-command.
Praveen Premaratne
1
Pintasan yang berfungsi untuk saya adalah Escape+ V, tetapi masih akan menjalankan perintah. Jadi untuk solusinya, saya akan menambahkan echodi depan untuk menjalankannya dengan mencetak perintah ke konsol untuk ditinjau.
kenorb
2
dapatkah Anda membuat contoh nyata? Saya tidak mengerti "menerapkan penyaringan tertentu (menggunakan skrip) dan kemudian mengembalikannya ke prompt".
Kent
3
@PraveenPremaratne: zsh bukan terminal , itu shell .
Arkadiusz Drabczyk

Jawaban:

7

Pembaruan terbaru tentang pengalaman saya

Bagian 0"+y$dd dalam pemetaan berikut ini adalah sesuatu yang harus Anda pikirkan dan sesuaikan dengan selera / alur kerja / pengalaman Anda.

Sebagai contoh, sangat sering saya menemukan diri saya berakhir dengan beberapa baris di buffer, di mana saya hanya ingin mengeksekusi satu kursor aktif; dalam hal ini saya dapat menggunakan 0"+y$dd:%d<CR>sebagai gantinya0"+y$dd .

Dan ini hanyalah salah satu skenario yang mungkin.

Jawaban akhir untuk mereka yang suka vim

Jawaban asli

Saya sering perlu melakukan hal yang sama, dan saya melakukannya sebagai berikut. (Saya biasanya menggunakan set -o viin bash, jadi poin 1 dan 2 berikut ini berbeda jika Anda menggunakan set -o emacs, default; berdasarkan pertanyaan Anda sepertinya poin 1 dan 2 disatukan dalam Ctrl+ xdiikuti oleh Ctrl+ e, yang lebih sulit untuk mengetik, ya .)

  1. tekan Escapeberada dalam mode normal,
  2. memukul v untuk masuk ke editor untuk mengedit perintah,
  3. edit perintah yang saya suka,

(Di sinilah Anda mengajukan pertanyaan.)

  1. memukul Escape0"+y$dd:wq,
    • Catatan:, 0"+y$tidak hanya "+yy, karena yang terakhir akan menyalin baris baru juga, dan ini akan menghasilkan mengeksekusi perintah setelah menempelkannya di baris perintah,
  2. rekatkan clipboard pada baris perintah
    • bagaimana melakukan ini tergantung pada terminal yang Anda gunakan, saya kira; Saya menekan Ctrl+ Alt+ vdalam URxvt.
  3. lanjutkan ke persetujuan / edit manual.

Jelas ini hanya solusi, yang terdiri dari menyalin perintah yang diedit ke clipboard sebelum menghapus seluruh perintah, sehingga tidak ada yang dieksekusi saat keluar dari editor; namun itu yang terbaik yang bisa saya dapatkan untuk diri saya sendiri.

Memperbarui

Karena saya EDITOR(dan VISUAL) sama dengan vim, ketika saya mengedit perintah, saya mengeditnyavim .

Dalam hal ini, saya perhatikan bahwa buffer bernama /tmp/bash-fc.random, di mana randomstring acak alfanumerik 6 karakter.

Ini memberi ruang bagi banyak kemungkinan, jika Anda gunakan vimsebagai editor, karena Anda dapat menentukan beberapa pemetaan di Anda .vimrcuntuk menjalankan seluruh urutan Escape0"+y$dd:wq. Misalnya, satu perintah yang jarang Anda gunakan saat mengedit baris perintah adalah Leaderd; karena itu Anda dapat meletakkan mapping berikut di .vimrcfile Anda

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

sehingga langkah 4 dalam resep di atas menjadi

  1. memukul EscapeLeaderd
Enrico Maria De Angelis
sumber
Bagi saya ini adalah cara terbaik untuk mengedit perintah
A.Villegas
2

Tidak mungkin melakukannya di Bash / readline tetapi dimungkinkan di zsh menggunakan edit-command-lineperintah:

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

Sekarang tekan Control- x Control- euntuk membuka editor Anda, edit baris, tinggalkan editor - Anda akan melihat baris perintah yang diperbarui tetapi tidak akan dieksekusi secara otomatis.

Arkadiusz Drabczyk
sumber
1

Sekarang saya berpikir tentang hal itu, mungkin variasi dari apa yang disarankan @kenorb dalam komentar adalah solusi terbaik (karena sepertinya tidak ada solusi), jika kita ingin tetap berpegang pada bash .

Apa yang dapat Anda lakukan adalah menambahkan #(karakter komentar di bash) ke perintah, bukan echo. Kemudian ketika Anda keluar dari exitor, perintahnya tidak akan efektif, dan Anda hanya perlu menekan arrow up(atau k, jika Anda menggunakan set -o vi), hapus #dan konfirmasikan.

Perhatikan bahwa strategi ini hanya menambahkan beberapa penekanan tombol, sehingga ini bisa sangat efisien, tergantung pada tingkat pengetikan Anda.

Enrico Maria De Angelis
sumber
1

Potongan-potongan ini mungkin membuat Anda lebih dekat:

a) mengganti ikatan normal untuk baris baru baris baru (ctrl-M) bind -x '"\C-M":date"

b) ambil garis saat ini dari riwayat menggunakan !#

ganti tanggal dengan skrip apa pun yang Anda inginkan.

c) edit secara manual

d) jika perlu, entah bagaimana mengikat !!:pyang mencetak perintah baru ke baris perintah tetapi tidak menjalankannya, sehingga memungkinkan Anda mengeditnya secara manual.

e) menggunakan ctrl-J mengirimkan perintah yang diedit daripada baris baru

atau mereka mungkin tidak ....

ShpielMeister
sumber
1

Ada opsi dalam bash untuk memodifikasi perintah dari histori tanpa menjalankannya. Saya tidak yakin apakah mungkin menggunakan skrip untuk ini, sepertinya tidak mungkin. Meskipun, Anda dapat membuat modifikasi menggunakan pengubah riwayat.

  1. Aktifkan opsi histverifikasi untuk mencegah eksekusi perintah yang dimodifikasi
  2. Gunakan rantai pengubah untuk mengubah perintah terakhir
  3. Gunakan "!!" untuk menempatkan hasil Anda ke baris perintah untuk edit terakhir

Berikut tampilannya:

$ 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
sumber
1

Saya ingin mengarahkan Anda ke kerangka kerja Composure untuk Bash (saya tidak berafiliasi dengannya): https://github.com/erichs/composure

Ini menyediakan draftdan revisefungsi-fungsi yang terdengar seperti mereka dapat membantu dengan apa yang Anda coba lakukan. Berikut ini kutipan (panjang) dari file readme proyek:

Composure membantu dengan membiarkan Anda dengan cepat menyusun fungsi shell sederhana, memecah filter pipa panjang dan perintah kompleks menjadi potongan yang dapat dibaca dan digunakan kembali.

Draf dulu, ajukan pertanyaan nanti

Setelah Anda membuat permata Anda dari perintah, jangan membuangnya! Gunakan draft ()dan berikan nama yang bagus. Ini menyimpan perintah terakhir Anda sebagai fungsi yang dapat Anda gunakan kembali nanti. Anggap saja seperti konsep kasar.

  $ 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

Revisi, revisi, revisi!

Sekarang Anda memiliki fungsi shell minimal, Anda mungkin ingin membuatnya lebih baik melalui refactoring dan revisi. Gunakan revise ()perintah untuk merevisi fungsi shell Anda di editor favorit Anda.

  • menggeneralisasi fungsi dengan parameter input
  • menambah atau menghapus fungsionalitas
  • tambahkan metadata pendukung untuk dokumentasi

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

Tampaknya tidak mungkin dengan pintasan keyboard, setidaknya:

$ 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
sumber