Angenommen, Ihre Datei ist natürlich weniger als 20.000 Zeilen lang :-)
paxdiablo
3
Eigentlich liegst du falsch Michael. Dies funktioniert einwandfrei, da VI das Makro nicht mehr ausführt, sobald es das Dateiende erreicht. Sie können es sehr einfach mit dem obigen Beispiel ausprobieren.
Rui
1
Nun, wie bei jedem Makro müssen Sie es beim ersten Mal richtig machen, aber danach können Sie es auf jede Datei anwenden, indem Sie einfach 10000 @ q eingeben. So oder so glaube ich, dass es nur eine Frage des Geschmacks ist, also werde ich definitiv keine philosophische Debatte beginnen. :)
Rui
3
Ich bevorzuge 'Makro'. Mit dem Makro beschreiben Sie, wie Sie eine bestimmte Aufgabe lösen würden, und lassen sie von VIM für Sie wiederholen. RUI, ich würde lieber 'j' anstelle der Pfeiltaste verwenden.
Eine elegante (und effiziente) Möglichkeit, die Aufgabe auszuführen, besteht darin, den :+deleteBefehl aufzurufen und die Zeile nach der aktuellen Zeile in jeder Zeile mit dem folgenden Befehl zu entfernen :global:
Warum hat diese Antwort nicht mehr Stimmen bekommen? Das ist so sauber und einfach. Alternativ können Sie die erste Zeile löschen und den obigen Befehl ausführen, um alle ungeraden Zeilen zu löschen.
Usagi
3
@Usagi: Danke! Mir geht es genauso. Und ja, Sie haben absolut Recht, :1d|g/^/+dlöscht die ungeraden Zeilen.
ib.
@Usagi Die andere Antwort wurde 2 Jahre vor Erscheinen seiner Antwort als "beste Antwort" ausgewählt. Auch wenn dies eine elegantere Lösung ist, hätte sie nützlicher geschrieben werden können (dh es wird nicht erwähnt, was ^ tut, während das Makro für jedermann leicht zu verstehen ist).
user1271772
3
Entschuldigung, aber ohne eine Erklärung, wie dieser Befehl das gewünschte Verhalten ausführt, würde ich ihn nicht positiv bewerten und stattdessen die akzeptierte Antwort bevorzugen, da ich verstehe, wie er das Ziel erreicht. Es ist der Unterschied, einem Mann einen Fisch zu geben und ihm das Fischen beizubringen.
Gabe
3
Ich weiß nicht, diese Antwort hat mich dazu gebracht, mit dem Befehl: g zu fischen (das heißt, ich habe diese Seite googelt - vim.wikia.com/wiki/Power_of_g ).
Snetch
67
Wir können gegebene Befehle im normalen Modus verwenden :normaloder :normausführen. Quelle.
Diese Antwort erhält nicht genügend Aufmerksamkeit, möglicherweise aufgrund der fehlenden Erklärung sowohl hier als auch auf dem verknüpften, chaotischen Spickzettel. Der Befehl norm führt die Befehle im normalen Modus aus, die den darauf folgenden Buchstaben entsprechen. Hier wird also j ausgeführt, um eine Zeile nach unten zu verschieben, und dd, um sie zu löschen. Dies ist auf die X. Zeile verallgemeinerbar, indem in diesem Fall weitere 'j' hinzugefügt werden.
Imoatama
5
und das% ist eine Abkürzung für 1, $ (führen Sie den folgenden Befehl von Zeile 1 bis zum Ende aus)
Lambart
3
Ich bin daran interessiert, warum %norm ddjes nicht funktioniert, wenn Sie ungerade Zeilen löschen möchten.
Cyker
10
:map ^o ddj^o
^o
Hier steht ^ für STRG. Rekursives Makro zum Löschen einer Zeile alle zwei Zeilen. Wählen Sie gut Ihre erste Zeile und es ist geschafft.
Dann würde ich es vorziehen !perl -ne 'print unless $. % 2':-)
Alex Brasetvik
Und, Alex, ich würde meine Lösung definitiv Ihrer vorziehen, aber diese ist eine Überlegung wert, da dies die einzig sinnvolle Lösung ist, bei der nur vim selbst verwendet wird.
Michael Krelin - Hacker
Der Makroweg ist so viel einfacher.
trusktr
+1 wegen der Flexibilität, mit if (expression)der auch für jede dritte Zeile usw. funktioniert
Jens
5
Sie können jederzeit einen Shell-Befehl durchlaufen, dh Sie können eine beliebige Skriptsprache verwenden:
:%!perl -nle 'print if $. % 2'
(oder verwenden Sie "es sei denn" anstelle von "wenn", je nachdem, welche Zeilen Sie möchten)
Sie brauchen den -lWechsel zu Perl nicht ... außerdem würde ich sagen, dass dies awketwas weiter verbreitet ist als Perl, obwohl es heutzutage nicht mehr so viel ist und dies kürzer machen kann: :%!awk NR\%2oder :%!awk 1-NR\%2für die anderen Zeilen.
Umm, warum nicht die vorhandene NRVariable verwenden?
Ephemient
Richtig. Weil ich es vergessen habe. ;-) Aber tatsächlich wird die "richtige" Variante mit NR noch länger sein. Und es würde keine zwei gut aussehenden Gegenstücke geben.
Michael Krelin - Hacker
:%!awk NR\%2oder :%!awk 1-NR\%2, wie ich in einem anderen Kommentar gepostet habe. Das geht kaum noch.
Ephemient
1
1-NRist länger als c++. Ja, ich weiß, dass es ein Charakter ist. Wie ich schon sagte - der wahre Grund ist, dass ich es vergessen habe. Wie auch immer, es sieht so aus, als würden die Leute die Schönheit von awk hier nicht schätzen.
Michael Krelin - Hacker
Und NRist kürzer als ++c:)
ephemient
3
Sie können die eigenen Such- und Ersatzfunktionen von Vim wie folgt verwenden: Setzen Sie den Cursor in die erste Zeile und geben Sie im normalen Modus Folgendes ein:
:.,/fff/s/\n.*\(\n.*\)/\1/g
Dies .,/fff/ist der Bereich für die Substitution. Es bedeutet "von dieser Zeile zu der Zeile, die dem regulären Ausdruck entspricht fff(in diesem Fall die letzte Zeile).
s///ist der Ersatzbefehl. Es sucht nach einem regulären Ausdruck und ersetzt jedes Vorkommen durch einen String. Das gam Ende bedeutet, die Ersetzung zu wiederholen, solange der reguläre Ausdruck gefunden wird.
Der \n.*\(\n.*\)reguläre Ausdruck entspricht einer neuen Zeile, dann einer ganzen Zeile ( .*entspricht einer beliebigen Anzahl von Zeichen mit Ausnahme einer neuen Zeile), dann einer weiteren neuen Zeile und einer weiteren Zeile. Die Klammern \(und \)bewirken, dass der Ausdruck in ihnen aufgezeichnet wird, damit wir ihn später verwenden können \1.
\1 Fügt die gruppierte neue Zeile und die Zeile danach wieder ein, da wir nicht möchten, dass auch die nächste Zeile weg ist. Wir möchten nur, dass der Substitutionsmechanismus daran vorbeigeht, damit wir sie beim nächsten Ersetzen nicht löschen.
Auf diese Weise können Sie den Bereich steuern, in dem das Löschen erfolgen soll, und Sie müssen kein externes Tool verwenden.
b = cb[:]kopiert vorübergehend alle Zeilen im aktuellen Puffer nach b. b[::2]holt jede zweite Zeile aus dem Puffer und weist sie dem gesamten aktuellen Puffer zu cb[:]. Das Kopieren nach bist erforderlich, da Pufferobjekte die erweiterte Slice-Syntax nicht zu unterstützen scheinen.
Dies ist wahrscheinlich nicht der "vim Weg", könnte aber leichter zu merken sein, wenn Sie Python kennen.
Suchen Sie nach Text (bildet die erste Zeile), gefolgt von einem neuen Zeilenzeichen und etwas mehr Text (bildet die zweite Zeile), gefolgt von einem weiteren neuen Zeilenzeichen, und ersetzen Sie das obige durch entweder erste Übereinstimmung (ungerade Zeile) oder zweite Übereinstimmung (gerade Zeile). gefolgt von Wagenrücklauf.
:% !sed -e '2~2 d'
^^^^ pipe file through a shell command
^^^^^^ the command is sed, and -e describes an expression as parameter
^^^^^ starting with the second line, delete every second line
Antworten:
Sie können hierfür ein Makro verwenden. Mach Folgendes.
gg
.qq
.dd
danach.q
.10000@q
PS: Um in den Befehlsmodus zu wechseln, drücken Sie einfach einige Male die Esc-Taste.
quelle
:g/^/+d
vom Benutzer stackoverflow.com/users/254635/ib ( unten ) ist eine elegantere Möglichkeit, dies zu lösen.Eine elegante (und effiziente) Möglichkeit, die Aufgabe auszuführen, besteht darin, den
:+delete
Befehl aufzurufen und die Zeile nach der aktuellen Zeile in jeder Zeile mit dem folgenden Befehl zu entfernen:global
:quelle
:1d|g/^/+d
löscht die ungeraden Zeilen.Wir können gegebene Befehle im normalen Modus verwenden
:normal
oder:norm
ausführen. Quelle.quelle
%norm ddj
es nicht funktioniert, wenn Sie ungerade Zeilen löschen möchten.Hier steht ^ für STRG. Rekursives Makro zum Löschen einer Zeile alle zwei Zeilen. Wählen Sie gut Ihre erste Zeile und es ist geschafft.
quelle
aus dem vim mail archiv :
(Wenn Sie in einer Zeile der vim-Befehlszeile eingeben, wird die Zeile 1,3,5,7, ... gelöscht.)
quelle
!perl -ne 'print unless $. % 2'
:-)if (expression)
der auch für jede dritte Zeile usw. funktioniertSie können jederzeit einen Shell-Befehl durchlaufen, dh Sie können eine beliebige Skriptsprache verwenden:
(oder verwenden Sie "es sei denn" anstelle von "wenn", je nachdem, welche Zeilen Sie möchten)
quelle
-l
Wechsel zu Perl nicht ... außerdem würde ich sagen, dass diesawk
etwas weiter verbreitet ist als Perl, obwohl es heutzutage nicht mehr so viel ist und dies kürzer machen kann::%!awk NR\%2
oder:%!awk 1-NR\%2
für die anderen Zeilen.Alternative
je nachdem welche hälfte du aussortieren willst.
quelle
NR
Variable verwenden?:%!awk NR\%2
oder:%!awk 1-NR\%2
, wie ich in einem anderen Kommentar gepostet habe. Das geht kaum noch.1-NR
ist länger alsc++
. Ja, ich weiß, dass es ein Charakter ist. Wie ich schon sagte - der wahre Grund ist, dass ich es vergessen habe. Wie auch immer, es sieht so aus, als würden die Leute die Schönheit von awk hier nicht schätzen.NR
ist kürzer als++c
:)Sie können die eigenen Such- und Ersatzfunktionen von Vim wie folgt verwenden: Setzen Sie den Cursor in die erste Zeile und geben Sie im normalen Modus Folgendes ein:
.,/fff/
ist der Bereich für die Substitution. Es bedeutet "von dieser Zeile zu der Zeile, die dem regulären Ausdruck entsprichtfff
(in diesem Fall die letzte Zeile).s///
ist der Ersatzbefehl. Es sucht nach einem regulären Ausdruck und ersetzt jedes Vorkommen durch einen String. Dasg
am Ende bedeutet, die Ersetzung zu wiederholen, solange der reguläre Ausdruck gefunden wird.\n.*\(\n.*\)
reguläre Ausdruck entspricht einer neuen Zeile, dann einer ganzen Zeile (.*
entspricht einer beliebigen Anzahl von Zeichen mit Ausnahme einer neuen Zeile), dann einer weiteren neuen Zeile und einer weiteren Zeile. Die Klammern\(
und\)
bewirken, dass der Ausdruck in ihnen aufgezeichnet wird, damit wir ihn später verwenden können\1
.\1
Fügt die gruppierte neue Zeile und die Zeile danach wieder ein, da wir nicht möchten, dass auch die nächste Zeile weg ist. Wir möchten nur, dass der Substitutionsmechanismus daran vorbeigeht, damit wir sie beim nächsten Ersetzen nicht löschen.Auf diese Weise können Sie den Bereich steuern, in dem das Löschen erfolgen soll, und Sie müssen kein externes Tool verwenden.
quelle
$
stattdessen/fff/
für das Dateiende, unabhängig vom Inhalt der Datei.Als weiteren Ansatz können Sie auch Python verwenden, wenn Ihr vim dies unterstützt.
b = cb[:]
kopiert vorübergehend alle Zeilen im aktuellen Puffer nachb
.b[::2]
holt jede zweite Zeile aus dem Puffer und weist sie dem gesamten aktuellen Puffer zucb[:]
. Das Kopieren nachb
ist erforderlich, da Pufferobjekte die erweiterte Slice-Syntax nicht zu unterstützen scheinen.Dies ist wahrscheinlich nicht der "vim Weg", könnte aber leichter zu merken sein, wenn Sie Python kennen.
quelle
So löschen Sie ungerade Zeilen (1,3,5, ..) ->
:%s/\(.*\)\n\(.*\)\n/\2\r/g
Gerade Zeilen löschen (2,4,6, ..) ->
:%s/\(.*\)\n.*\n/\1\r/g
Suchen Sie nach Text (bildet die erste Zeile), gefolgt von einem neuen Zeilenzeichen und etwas mehr Text (bildet die zweite Zeile), gefolgt von einem weiteren neuen Zeilenzeichen, und ersetzen Sie das obige durch entweder erste Übereinstimmung (ungerade Zeile) oder zweite Übereinstimmung (gerade Zeile). gefolgt von Wagenrücklauf.
quelle
Sed aufrufen:
quelle
Lösung
Sie können dies in vim versuchen
bearbeiten
Ich werde versuchen, klarer zu sein (zwei Teile)
erster Teil der Auswahlbereich (
:from,to
)zweiter Teil die Aktion (
d
löschen):1,$-1
)g
) delete (+1d
) nächste ZeileSie können versuchen, in die erste Zeile Ihrer Datei zu wechseln und diese auszuführen.
:+1d
Die nächste Zeile wird ausgeblendetIch weiß, dass es schlammig ist, aber es ist vim und es funktioniert
quelle