Von der Hilfe :help backtick-expansion
:
On Unix and a few other systems you can also use backticks for the file name
argument, for example:
:next `find . -name ver\\*.c -print`
:view `ls -t *.patch \| head -n1`
The backslashes before the star are required to prevent the shell from
expanding "ver*.c" prior to execution of the find program. The backslash
before the shell pipe symbol "|" prevents Vim from parsing it as command
termination.
Wenn ich den Befehl aus der Hilfe eingebe, wird folgende Fehlermeldung angezeigt:
:next `find . -name ver\\*.c -print
E79: Cannot expand wildcards
Warum verwendet das Beispiel aus der Hilfe zwei Backslashes anstelle von einem und warum funktioniert es nicht?
Die folgende Arbeit:
Wenn ich einen der beiden Backslashes entferne, die den Stern vor der Erweiterung durch die Shell vor dem
find
Programm schützen ::next `find . -name ver\*.c -print`
Wenn ich beide Backslashes entferne und einfache Anführungszeichen um das Muster setze
ver*.c
::next `find . -name 'ver*.c' -print`
Bis zu diesem Punkt scheint die Regel zu lauten:
Wenn Ihr Shell-Befehl einen Stern enthält und Sie nicht möchten, dass die Shell ihn vor dem Befehl erweitert, setzen Sie einen Backslash davor oder setzen Sie einfache Anführungszeichen um das Muster .
Aber die Hilfe gibt ein anderes Beispiel:
:view `ls -t *.patch \| head -n1`
Dieser Befehl funktioniert ohne Änderungen, ohne einfache Anführungszeichen und ohne umgekehrten Schrägstrich.
Ich nehme an, der Grund, warum es funktioniert, ist, dass der ls
Befehl (im Gegensatz zum -name
Argument des find
Befehls) mehrere Dateiargumente akzeptiert und kein Problem mit der Erweiterung der Shell sieht *.patch
.
Nun lassen Sie uns sagen , dass ich für alle Dateien mit der Erweiterung aussehen wollen .conf
in den /etc
Ordner und Rohren die Ausgabe find
auf grep
nur die Spiele zu bekommen die Zeichenfolge enthält input
.
In die Shell würde ich aus jedem Arbeitsverzeichnis Folgendes eingeben:
find /etc -name '*.conf' | grep input
Und es würde funktionieren.
In vim gebe ich denselben Befehl ein, indem ich Backticks um ihn herum und einen Backslash vor dem Pipe-Symbol einfüge, um zu verhindern, dass vim ihn als Befehlsbeendigung interpretiert:
:next `find /etc -name '*.conf' \| grep input`
Und es funktioniert.
Wenn ich jetzt denselben Befehl ohne Pipe und Pipe grep input
eingebe, wird folgende Fehlermeldung angezeigt:
:next `find /etc -name '*.conf'`
E79: Cannot expand wildcards
Warum liegt in diesem Fall ein Fehler vor, obwohl ich den Stern mit einfachen Anführungszeichen geschützt habe?
Und warum gibt es jetzt einen Fehler, aber nicht erst vorher mit der Pipe und der grep input
?
Zum besseren Verständnis habe ich mir einen einfacheren Befehl ausgedacht:
find . -name '*.conf'
Es sucht nach allen Dateien mit der Erweiterung .conf
im Arbeitsverzeichnis. Der Befehl funktioniert in der Shell.
Um es in vim zu testen, habe ich Folgendes eingegeben: :next `find . -name '*.conf'`
Und es funktioniert. In diesem Fall steht der Punkt für mein aktuelles Arbeitsverzeichnis, wie es vom Befehl Ex angezeigt wird. Dies :pwd
ist mein Ausgangsverzeichnis, /home/username
seit ich die vim-Sitzung von dort aus gestartet habe.
Warum funktioniert es, wenn ich nach dem aktuellen Arbeitsverzeichnis frage, während es nicht funktioniert, wenn ich nach einem beliebigen Ordner wie z /etc
.
Wenn ich nun mein Arbeitsverzeichnis mit dem Befehl vim Ex von /home/username
auf ändere und denselben Befehl wie zuvor erneut versuche, tritt erneut ein Fehler auf:/etc
:cd /etc
:next `find . -name '*.conf'`
E79: Cannot expand wildcards
Warum funktioniert der gleiche Befehl, wenn ich in meinem Home-Ordner bin, aber nicht, wenn ich in bin /etc
?
Ich bin mir sicher, dass es eine Logik gibt, aber ich kann keine finden.
Wie lautet die allgemeine und korrekte Syntax, um die Arglist mit einem beliebigen Shell-Befehl zu füllen (der einen Stern oder eine Pipe enthält und in einem beliebigen Verzeichnis aus einem beliebigen Arbeitsverzeichnis sucht)?
Ich verwende vim Version 7.4.942 und zsh ist meine Standard-Shell. Ich habe diese Befehle mit einem Minimum an Initialisierungen ( vim -u NORC -N
) sowohl von bash als auch von zsh getestet .
Muss ich vim so konfigurieren, dass bash und nicht zsh aufgerufen wird?
quelle
vim $(find . -name ver*.c)
vim $(find . -name ver\*.c -print)
,vim $(ls -t *.patch | head -n1)
,vim $(find /etc -name '*.conf' | grep input)
,vim $(find /etc -name '*.conf')
,vim $(find . -name '*.conf')
--remote
siehe: vi.stackexchange.com/a/5618/4939 ), aber ich bin gespannt, wie es geht Mach es direkt aus der aktuellen Sitzung. Wenn es nicht möglich ist, ist das in Ordnung, aber nach dem Lesen der Hilfe scheint es möglich zu sein. Wenn ja, würde ich gerne verstehen, warum vim auf ähnliche Befehle so unterschiedlich reagiert.find /etc -name '*.conf'
nicht funktioniert, würde denken , dass ich ein paar lustigen Namen dieses Befehl kommen, und dies ist der Grund sein, warum es funktionierte , als geleitet durchgrep
.Antworten:
Ich weiß immer noch nicht, wie ich die Backtick-Erweiterung verwenden soll, um die Arglist mit einem beliebigen Shell-Befehl zu füllen, aber ich habe eine Problemumgehung gefunden.
Von
:help `=
:Anstatt einen Shell-Befehl wie diesen direkt zu erweitern:
Wir können den Shell-Befehl an die Vim-Funktion senden
systemlist()
und das Ausdrucksregister verwenden=
, um den resultierenden Ausdruck wie folgt zu erweitern:Um einige Tastenanschläge zu speichern, habe ich in meinem vimrc (
:PA
für Populate Arglist) den folgenden Ex-Befehl definiert :Und testete es mit verschiedenen Shell-Befehlen:
Bisher funktioniert es wie erwartet und der Befehl kann wie in der Shell eingegeben werden (es ist beispielsweise nicht erforderlich, die Pipe zu verlassen).
Es scheint konsistenter und zuverlässiger zu sein als die direkte Backtick-Erweiterung.
quelle