Wie bearbeite ich Inhalte aus der Standardeingabe?

15

Ich möchte Inhalte in vim bearbeiten, die dynamisch über die Befehlszeile generiert wurden, ohne dass die Datei noch vorhanden ist.

Zum Beispiel:

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

aber es scheitert mit den Fehlern:

Vim: Warnung: Die Eingabe erfolgt nicht über ein Terminal

Vim: Fehler beim Lesen der Eingabe, beim Beenden ...

Ist es möglich, das zu erreichen?

Kenorb
quelle
:help stdin... Es ist erstaunlich, wie schnell man die Antworten finden kann, wenn man die Frage nach der eingebauten Dokumentation stellt.
Dash-Tom-Bang

Antworten:

23

Sie müssen -anstelle des Dateinamens in der Befehlszeile Folgendes verwenden:

echo This is example. | vim -

Der obige Befehl öffnet einen unbenannten Puffer, der mit dem aus der Standardeingabe gelesenen Text gefüllt ist.

toro2k
quelle
7
Die Verwendung von a -für stdin ist für Befehlszeilentools so ziemlich Standard.
Martin Tournoij
6

Dies ist meistens nur eine spaßige Notiz über bashund readline, aber wenn Sie Ihre EDITORUmgebungsvariable auf setzen vim, wird durch Drücken von Ctrl+ x+ edie aktuelle Zeile in geöffnet vim. Wenn Sie Meta(Alt/Opt/Esc)++ Ctrleingeben e, führt bash außerdem eine direkte Erweiterung der aktuellen Befehlszeile durch, dh:

$ echo $EDITOR # Assuming EDITOR was set

mit Meta(Alt/Opt/Esc)+ Ctrl+ ewürde werden

$ echo vim # Assuming EDITOR was set

mit Ctrl+ x+ ewürde werden

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

Beachten Sie, dass beim Beenden von vim der Inhalt des vim-Puffers in der Befehlszeile ausgeführt wird.

Diese Funktionen sind für mich sehr nützlich, wenn ich mehrzeilige Befehle in bash ausführen möchte, z. B. für Schleifen oder Programme, die diese Anweisungen erfordern, und sie bieten eine interessante Möglichkeit, einen Teil des Befehlszeilenverlaufs zur späteren Verwendung in einer Datei zu speichern.

Um die ursprüngliche Frage zu beantworten, können Sie auch schreiben:

$ This is an example

und drücke dann Ctrl+ x+ e, um es zu laden vim. Sie könnten auch haben,

 $ $(cat /etc/hosts)

und do Meta(Alt/Opt/Esc)+ Ctrl+ ethen Ctrl+ x+ e, wodurch alle Hosts-Dateien in eine Zeile geschrieben und geladen werden vim(wahrscheinlich nicht die beste Verwendung dieser Funktionen - die Nützlichkeit dieser Methoden kann jedoch aus den wenigen diskutierten Beispielen extrapoliert werden Hier).

Beachten Sie, dass ich davon ausgehen , dass Ihr readlinegesetzt ist emacsModus. Wenn Ihr Modus aktiviert readlineist, vimkönnen Sie die relevanten Bindungen mit dem folgenden Befehl leicht ermitteln:

bind -p

und Suchen nach edit-and-execute-commandoder shell-expand-line, die wurden jeweils in Verbindung mit den Bindungen Ctrl+ x+ eund Meta(Alt/Opt/Esc)+ Ctrl+ e.

HAL 9001
quelle
Sie können bash anweisen, vi-Tastenkombinationen anstelle von Emacs zu verwenden. Verwenden Sie, set -o vium es einzuschalten. Dann können Sie das vMapping einfach im normalen Modus verwenden, um den aktuellen Befehl in Ihrem Editor zu bearbeiten.
Quincy Bowers
1
Dies ist zwar ein großartiger Trick, um die Befehlszeile mit vi zu bearbeiten, aber es gibt mindestens zwei Probleme shell-expand-line, wenn Sie mit dieser Methode Text aus stdin lesen: 1. Entfernen Sie Zeilenumbrüche aus dem erweiterten Text und 2. edit-and-execute-commandVersuchen Sie, den im Puffer geschriebenen Befehl auszuführen , was auch immer gespeichert wird oder nicht, wenn Sie vi beenden.
toro2k
Woah, das ist großartig. Ich lerne jeden Tag etwas Neues über Readline ...
Türknauf
2

In Bash fand ich es nützlich, die Prozessersetzung mithilfe der <(command)Syntax zu verwenden. Beispiel:

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

Siehe auch:

Kenorb
quelle
4
Beachten Sie, dass dies nicht in allen Shells funktioniert. Ich denke , es wird nur funktionieren , in bashund zsh(und nicht sh, ksh, dash, fish, csh, tcsh, etc.)
Martin Tournoij
@Carpetsmoker Sollte in ksh88 und höher funktionieren, denke ich, aber ja, die Prozessersetzung ist kein POSIX.
muru
4
Und achte darauf, dich nicht zu betrügen! Wenn Sie Vim auf diese Weise starten, wird ein Puffer für eine Datei wie geöffnet /proc/PID/fd/FD. Wenn Sie den Puffer schreiben und beenden, beschwert sich Vim nicht, aber die Datei, in die Sie geschrieben haben, wird vom Betriebssystem entfernt. Wenn Sie -als Dateinamen für den geöffneten Puffer keine Datei angeben, werden Sie gewarnt, wenn Sie versuchen, den Vorgang zu beenden, ohne Vim zu speichern (sofern Sie keinen Bang-Befehl oder ähnliches verwenden).
toro2k
1
Das ist schön, weil es sich gut verallgemeinert vimdiff <(echo foo) <(echo bar).
wchargin
@ toro2k Im Nachhinein sieht es so aus, als ob Sie den Stream verwenden :nextund :preverneut lesen und nichts erhalten. Es ist auch erwähnenswert, dass die Prozesse nicht parallel zueinander sind - z. B. cat <(sleep 3; echo a) <(echo b)Drucke in der richtigen Reihenfolge - und während catInterleaves schreiben und lesen, darauf vimwarten, dass die Datei "fertig gelesen" wird, bevor alle außer dem äußeren Frame angezeigt werden.
John P
0

Wenn die Verwendung einer Pipeline für ein neues Vim nicht erforderlich ist, können Sie die Fähigkeit von Vim verwenden, die Ausgabe von Befehlen in den aktuellen Puffer zu ziehen, zusammen mit einem nicht dateibasierten Puffer (wie bei :newoder dem Bearbeiten einer nicht vorhandenen Datei).

:read!cat /etc/hosts Im Befehlsmodus wird die Ausgabe in Ihrem aktuellen Puffer unterhalb der aktuellen Cursorposition platziert.

Abgesehen davon, dass die leere erste Zeile gelöscht werden muss, wenn dies in einem leeren Puffer erfolgt, funktioniert dies gut und ist besonders praktisch, wenn Vim bereits ausgeführt wird.

ewatt
quelle
1
Wie beantwortet dies die Frage?
muru
Es nimmt die Ausgabe des Befehls und legt sie in vim ab.
Ewatt