Manchmal muss ich Text schreiben und diesen dann in einen anderen Befehl umleiten. Mein üblicher Workflow sieht ungefähr so aus:
vim
# I edit and save my file as file.txt
cat file.txt | pandoc -o file.pdf # pandoc is an example
rm file.txt
Ich finde das umständlich und versuche, Bash-Scripting zu lernen. Ich möchte den Prozess viel einfacher machen, indem ich einen Befehl schreibe, der einen Editor öffnet und wenn der Editor schließt, die Ausgabe des Editors an stdout weiterleitet. Dann könnte ich den Befehl als ausführen quickedit | pandoc -o file.pdf
.
Ich bin mir nicht sicher, wie das funktionieren würde. Ich habe bereits eine Funktion zur Automatisierung dieses Vorgangs geschrieben, indem ich den oben beschriebenen exakten Arbeitsablauf sowie einige Ergänzungen befolgt habe. Es generiert eine zufällige Zeichenfolge, die als Dateiname fungiert, und übergibt diese beim Aufruf der Funktion an vim. Wenn der Benutzer vim durch Speichern der Datei beendet, druckt die Funktion die Datei auf der Konsole und löscht sie dann.
function quickedit {
filename="$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-f0-9' | head -c 32)"
vim $filename
cat $filename
rm $filename
}
# The problem:
# => Vim: Warning: Output is not to a terminal
Das Problem, auf das ich bald gestoßen bin, ist, dass ich so etwas wie quickedit | command
vim selbst nicht als Editor verwenden kann, weil die gesamte Ausgabe auf die Pipe beschränkt ist.
Ich frage mich, ob es irgendwelche Problemumgehungen gibt, damit ich die Ausgabe meiner quickedit
Funktion weiterleiten kann. Die suboptimale Alternative ist, einen separaten Editor zu starten, z. B. erhabenen Text, aber ich möchte wirklich im Terminal bleiben.
:w !pandoc -o file.pdf
? (Hinweis: Der Abstand zwischenw
und!
ist von wesentlicher Bedeutung.)mktemp
anstatt es unsicher neu zu erfinden.Antworten:
vipe
ist ein Programm zum Bearbeiten von Pipelines:Sie erhalten einen Editor mit der vollständigen Ausgabe von
command1
und beim Verlassen werden die Inhaltecommand2
über die Pipe weitergeleitet.In diesem Fall gibt es keine
command1
. Sie könnten also Folgendes tun:Oder:
vipe
greift die VariablenEDITOR
und aufVISUAL
, sodass Sie sie zum Öffnen von Vim verwenden können.Wenn Sie es nicht installiert haben,
vipe
ist es immoreutils
Paket enthalten.sudo apt-get install moreutils
oder was auch immer Ihr Geschmacksäquivalent ist.quelle
moreutils
ist in Homebrew verfügbar.moreutils
über pkg (8) installiert werden .Sie können dies aus Vim heraus tun:
Oder schreiben Sie den Puffer in eine komplexe Pipeline:
Und dann können Sie Vim beenden, ohne zu speichern:
In Anbetracht Ihres speziellen Anwendungsfalls gibt es jedoch wahrscheinlich eine bessere Lösung,
vi
wenn Sie als Befehlszeileneditor verwenden. Angenommen, Sie verwendenbash
:Hiermit setzen Sie Ihre Tastenkombinationen auf
vi
. So können Sie Ihre Befehle direkt auf der Kommandozeile mit grundlegenden bearbeitenvi
keybindings durch Drücken<Esc>
und dann die Eingabe -vi
Befehle wiex
,cw
etc. (Sie können durch Drücken in Insert - Modus zurücki
.)Noch besser und relevanter für diese Frage ist, dass Sie Vim öffnen können, um Ihren Befehlszeileninhalt direkt zu erstellen. Geben
<Esc>v
Sie einfach ein und Sie erhalten einen leeren Vim-Puffer. Wenn Sie speichern und beenden, ist dies der Befehl in Ihrer Befehlszeile, der sofort ausgeführt wird. Dies ist viel flexibler als das direkte Bearbeiten über die Befehlszeile, da Sie ein ganzes Miniskript schreiben können, wenn Sie möchten.Wenn Sie beispielsweise einen schwierigen Text schreiben und ihn sofort an pandoc weiterleiten möchten, können Sie einfach Folgendes eingeben:
Bearbeiten Sie dann den Vim-Puffer, bis Sie ungefähr Folgendes haben:
Dann speichern und beenden (mit
:x
) und das Ganze wird als Shell-Befehl ausgeführt.Es ist auch im Befehlsverlauf Ihrer Shell verfügbar.
quelle
EDITOR
Umgebungsvariable auf setzenvim
undCtrl-X
gefolgt von drücken,Ctrl-E
während Sie die Befehlszeile bearbeiten.Laufen in einer Pipeline
Versuchen:
Der Schlüssel ist, dass, um
vim
normal arbeiten zu können,vim
stdout als Terminal benötigt wird. Das erreichen wir hier mit dem Redirect>/dev/tty
.Aus Sicherheitsgründen habe ich die temporäre Datei in das Ausgangsverzeichnis des Benutzers gestellt. Weitere Informationen hierzu finden Sie in Gregs FAQ, Frage 062 . Dadurch entfällt die Verwendung eines unklaren Dateinamens.
Beispiel:
Beim
vim
Öffnen gebe ichThis function succeeded.
die Datei ein und speichere sie. Das Ergebnis auf dem Bildschirm sieht folgendermaßen aus:Auch wenn die Ausgabe von
quickedit
an eine Pipeline umgeleitet wird,vim
funktioniert sie normal, da wir direkten Zugriff darauf gewährt haben/dev/tty
.Ausführen eines Programms aus vim heraus
Wie ich in den Kommentaren erwähnt habe, kann vim eine Datei an einen Befehl weiterleiten. Geben Sie beispielsweise in vim den Befehl ein
:w !pandoc -o file.pdf
(Hinweis: Der Abstand zwischen w und! Ist von wesentlicher Bedeutung).quelle
trap '...' exit
schlägt fehl,trap '...' EXIT
scheint aber zu funktionieren. Ich weiß nicht viel über Überfüllung, aber mein allgemeiner Ansatz für temporäre Dateien ist zu verwendenmktmp [--suffix=...]
. Wirdvim <outfile> -c '...' >/dev/tty
wie gewohnt ausgeführt, bis die Datei geladen ist, und führt dann die angegebene Befehlskette aus, auch:wq
wenn Sie die Bearbeitungsphase überspringen möchten. Ich habe auch verwendetset | grep -a EXIT
und gefundensignals=(EXIT ... DEBUG)
.Stellen Sie sicher, dass dies
vim
als Standardeditor festgelegt ist (z . B.export EDITOR=vim
in Ihrem.bash_profile
oder.bashrc
. Dann können Sie an jeder Eingabeaufforderung Folgendes eingeben: Ctrl- Xgefolgt von Ctrl- E. Dadurch wird Ihre aktuelle Befehlszeile in Ihrem konfigurierten Editor geöffnet (zvim
. B. ). Nehmen Sie Ihre Änderungen vor, speichern und exit, und der Befehl wird ausgeführt, als ob Sie ihn in der Befehlszeile eingegeben hätten, einschließlich Pipelines und dergleichen.quelle