2017-07-25 5 views
3

Ich versuche, eine Reihe von Dateien zu verarbeiten. Ich habe bemerkt, dass es Diskrepanzen beim Ausführen eines bestimmten Befehls von der Befehlszeile gibt (d. H. ex Modus). Z.B.Unterschiede in der Ausführung von vim über die Befehlszeile im Vergleich zum Ausführen im vim-Editor

$cat poo.txt 
big 
red 
dog 
small 
black 
cat 

$vim -c "2,$g/^dog/d|wq" poo.txt 

$cat poo.txt 
big 
small 
black 
cat 

Es scheint, dass 2,$g/^dog/d|wq die Linien mit red und dog gelöscht. Das verwirrt mich, weil der Befehl: in Zeile 2 (gehe zu EOF) starten und alle Zeilen löschen soll, die mit dog beginnen. In diesem Fall würde ich die Ausgabe erwarten:

$ cat poo.txt 
big 
red 
small 
black 
cat 

In der Tat, wenn ich dies in dem Editor vim versuchen ist dies das genaue Verhalten, das beobachtet wird.

FRAGE: Was ist die Ursache für die Diskrepanz zwischen der vim -c Version und der vim Version dieses Befehls ausführen?

Antwort

3

Ich denke, Sie müssen die doppelten Anführungszeichen durch einfache Anführungszeichen ersetzen, um zu verhindern, dass sich Ihre Shell ausdehnt $g. Von man bash:

Enclosing characters in double quotes preserves the literal value of all 
characters within the quotes, with the exception of $, `, \, and, 
when history expansion is enabled, !. 

Derzeit erweitert die Shell $g in Ihrem String, als ob es eine Umgebungsvariable war. Aber es ist wahrscheinlich nicht definiert, dehnt sich also in eine leere Zeichenfolge aus. Also, auch wenn Sie schon getippt:

vim -c "2,$g/^dog/d|wq" poo.txt 

Vim nicht empfängt den Befehl:

2,$g/^dog/d|wq 

... aber:

2,/^dog/d|wq 

Dieser Befehl löscht alle Zeilen aus derjenige, dessen Adresse 2 ist, zu dem nächsten, der mit dog beginnt (in Ihrem Fall ist es die 3. Zeile). Dann speichert und beendet.

Aber auch wenn Sie die Anführungszeichen ersetzen, gibt es immer noch ein Problem in Ihrem Befehl. Von :h :bar:

These commands see the '|' as their argument, and can therefore not be 
followed by another Vim command: 

... 
:global 
... 

Die Bar wird von :g als Teil ihres Arguments interpretiert, nicht als Befehl Terminierung. In Ihrem Fall bedeutet das, dass es immer dann, wenn es eine Zeile findet, die mit dog beginnt, es löscht, dann sofort speichert und beendet. Wenn also mehrere dog Zeilen vorhanden sind, wird nur die erste Zeile gelöscht, da :g gespeichert und nach der Verarbeitung der ersten Datei beendet wurde.

Sie müssen |wq von :g verstecken, indem Sie entweder den globalen Befehl in einem String Einwickeln und es mit :execute Ausführung oder durch wq in einer anderen -c {cmd} bewegen.Alles in allem könnten Sie versuchen:

vim -c 'exe "2,\$g/^dog/d" | wq' poo.txt 

oder

vim -c '2,$g/^dog/d' -c 'wq' poo.txt 

oder

vim -c '2,$g/^dog/d' -cx poo.txt 
Verwandte Themen