Bagaimana cara mengedit konten dari input standar?

15

Saya ingin mengedit konten dalam vim yang dihasilkan secara dinamis dari command-line tanpa memiliki file.

Sebagai contoh:

$ echo This is example. | vim /dev/stdin
$ cat /etc/hosts | vim /dev/stdin

tetapi gagal dengan kesalahan:

Vim: Peringatan: Input bukan dari terminal

Vim: Kesalahan saat membaca input, keluar ...

Apakah mungkin untuk mencapai itu?

kenorb
sumber
:help stdin... Sungguh luar biasa seberapa cepat seseorang dapat menemukan jawaban dengan mengajukan pertanyaan mereka tentang dokumentasi bawaan.
dash-tom-bang

Jawaban:

23

Anda harus menggunakan -tempat nama file pada baris perintah:

echo This is example. | vim -

Perintah di atas akan membuka buffer tanpa nama yang diisi dengan teks yang dibaca dari input standar.

toro2k
sumber
7
Menggunakan -for stdin cukup banyak standar untuk alat commandline;
Martin Tournoij
6

Ini hanya sebagian besar catatan yang menyenangkan tentang bashdan readline, tetapi jika Anda mengatur EDITORvariabel lingkungan Anda vim, menekan Ctrl+ x+ eakan membuka baris saat ini vim. Selanjutnya, jika Anda mengetik Meta(Alt/Opt/Esc)+ Ctrl+ e, bash akan melakukan ekspansi di tempat pada baris perintah saat ini, yaitu:

$ echo $EDITOR # Assuming EDITOR was set

dengan Meta(Alt/Opt/Esc)+ Ctrl+ eakan menjadi

$ echo vim # Assuming EDITOR was set

dengan Ctrl+ x+ eakan menjadi

1 echo vim # Assuming EDITOR was set
~
~
/tmp/sometmpbufferfile

Perhatikan bahwa setelah berhenti vim, isi buffer vim dieksekusi pada baris perintah.

Fitur-fitur ini menjadi sangat berguna bagi saya ketika saya ingin melakukan perintah multi-line di bash seperti untuk loop atau program yang membutuhkan pernyataan di sini, dan menyediakan cara yang menarik untuk menyimpan sedikit sejarah baris perintah ke file untuk digunakan nanti.

Jadi untuk menjawab pertanyaan awal, Anda juga bisa menulis,

$ This is an example

dan kemudian tekan Ctrl+ x+ euntuk memuatnya vim. Anda juga bisa,

 $ $(cat /etc/hosts)

dan lakukan Meta(Alt/Opt/Esc)+ Ctrl+ elalu Ctrl+ x+ e, yang akan menempatkan semua file host pada satu baris dan memuatnya vim(mungkin bukan penggunaan terbaik dari fitur-fitur ini - namun, kegunaan metode ini dapat diekstrapolasi dari beberapa contoh yang dibahas sini).

Perhatikan bahwa saya menganggap bahwa Anda readlinediatur ke emacsmode. Jika Anda readlinediatur ke vimmode Anda dapat dengan mudah menemukan binding yang relevan dengan menggunakan perintah:

bind -p

dan mencari edit-and-execute-commandatau shell-expand-line, yang masing-masing terkait dengan binding Ctrl+ x+ edan Meta(Alt/Opt/Esc)+ Ctrl+ e.

HAL 9001
sumber
Anda bisa memberi tahu bash untuk menggunakan binding kunci vi dan bukan emacs. Gunakan set -o viuntuk menyalakannya. Kemudian Anda bisa menggunakan vpemetaan dalam mode normal untuk mengedit perintah saat ini di editor Anda.
Quincy Bowers
1
Untuk memastikan ini adalah trik yang bagus untuk mengedit baris perintah menggunakan vi tetapi setidaknya ada dua masalah menggunakan metode ini untuk membaca teks dari stdin: 1. shell-expand-linemenghapus baris baru dari teks yang diperluas dan 2. edit-and-execute-commandmencoba untuk mengeksekusi perintah yang ditulis dalam buffer , apa pun itu disimpan atau tidak, ketika Anda berhenti vi.
toro2k
Woah, ini luar biasa. Saya belajar hal baru tentang readline setiap hari, sepertinya ...
Doorknob
2

Dalam bash saya merasa bermanfaat untuk menggunakan proses substitusi menggunakan <(command)sintaks, misalnya:

vim <(echo This is example.)
vim <(cat /etc/hosts)

Lihat juga:

kenorb
sumber
4
Perhatikan ini tidak akan bekerja di semua shell. Saya pikir itu hanya akan bekerja di bashdan zsh(dan tidak sh, ksh, dash, fish, csh, tcsh, dll)
Martin Tournoij
@Carpetsmoker Harus bekerja di ksh88 dan di atas, saya pikir, tapi ya, proses substitusi bukan POSIX.
muru
4
Dan perhatikan untuk tidak menipu diri sendiri! Ketika Anda memulai Vim dengan cara ini membuka buffer untuk file seperti /proc/PID/fd/FD. Jika Anda menulis buffer dan berhenti, Vim tidak mengeluh, tetapi file yang Anda tulis akan dihapus oleh OS. Menggunakan -sebagai nama file, buffer yang dibuka tidak memiliki file yang terkait dengannya jadi jika Anda mencoba untuk berhenti tanpa (selama Anda tidak menggunakan perintah bang atau serupa) menyimpan Vim akan memperingatkan Anda.
toro2k
1
Ini bagus karena bisa digeneralisasikan dengan baik vimdiff <(echo foo) <(echo bar).
wchargin
@ toro2k Untuk menindaklanjuti, sepertinya menggunakan :nextdan :prevmembaca ulang aliran dan tidak mendapatkan apa-apa. Perlu juga disebutkan bahwa prosesnya tidak sejajar satu sama lain - misalnya cat <(sleep 3; echo a) <(echo b)cetakan berurutan - dan sementara catinterleaves menulis dan membaca, vimmenunggu file untuk "selesai membaca" sebelum menampilkan semua kecuali kerangka luar.
John P
-1

Jika menggunakan pipa ke Vim baru bukan keharusan, Anda dapat menggunakan kemampuan Vim untuk menarik output perintah ke buffer saat ini, ditambah dengan memiliki buffer yang didukung file-non (seperti dengan :newatau mengedit file yang tidak ada)

:read!cat /etc/hosts dalam mode perintah akan menempatkan output ke buffer Anda saat ini di bawah posisi kursor saat ini.

Selain harus menghapus baris pertama kosong yang tersisa saat ini dilakukan pada buffer kosong, ini bekerja dengan baik dan sangat nyaman jika Vim sudah berjalan.

ewatt
sumber
1
Bagaimana ini menjawab pertanyaan?
muru
Dibutuhkan output dari perintah dan membuatnya menjadi vim.
ewatt