Möchten Sie eine Suche durchführen und in einer Datei mit 12000 Zeilen ersetzen.
Insbesondere wenn ein Vorkommen von ^ SetFontSize 28
nach einem ^Hide
Block und vor dem nächsten ^Hide
oder vorhanden ist ^Show
, ändern Sie 28
zu 18
.
Hier ist ein Ausschnitt aus der Originaldatei.
Hide # Gear - Endgame
ItemLevel >= 77
Rarity = Magic
LinkedSockets >= 3
BaseType "Runic Hatchet"
SetTextColor 140 190 255 # Magic Item Highlight
SetFontSize 28
Hide # Gear - Endgame
ItemLevel >= 77
Rarity = Magic
Sockets >= 3
BaseType "Runic Hatchet"
SetTextColor 140 190 255 # Magic Item Highlight
SetFontSize 28
Show # Gear - Endgame
ItemLevel >= 83
Rarity = Normal
Sockets < 3
BaseType "Tiger Hook"
SetTextColor 240 240 240 # Normal Item Highlight
SetBackgroundColor 70 70 70
SetFontSize 28
Das Endergebnis für einen der Hide
Blöcke sollte folgendermaßen aussehen:
Hide # Gear - Endgame
ItemLevel >= 77
Rarity = Magic
LinkedSockets >= 3
BaseType "Runic Hatchet"
SetTextColor 140 190 255 # Magic Item Highlight
SetFontSize 18
Ersetzen SetFontSize 28
zu SetFontSize 18
, aber nur, wenn es in einem ^Hide
Block erscheint.
Der böse Regex, den ich versuchte, war:
:%s/^Hide\(.*\)SetFontSize 28$/Hide\1SetFontSize 18/g
Aber wurde gesagt, Muster nicht gefunden. Bitte lassen Sie mich wissen, wenn zusätzliche Informationen erforderlich sind oder wenn meine Anfrage unklar ist.
Hide
Block eineSetFontSize
Zeile (was auch immer der Wert sein mag)? Wenn ja, könnten Sie verwenden:%s/Hide\_.\{-\}SetFontSize \zs28/18/
whatever be the value
würde Probleme verursachen, Ihre Lösung funktioniert nur, wenn jederHide
Block eineSetFontSize
Zeile hat und der Wert genau ist28
, andernfalls stimmt er bis28
zu einem anderen Block überein .Antworten:
Eine Möglichkeit, dies zu lösen, wäre die Verwendung
:global
einer Bereichsausgabe.Typische Verwendung des
global
Befehls wäreEs besteht auch die Möglichkeit, dass dieses Muster einen Bereich anstelle einer einzelnen Linienübereinstimmung generiert, indem es
,
in Form von verwendet wirdDadurch wird ein Bereich generiert, der auf den Befehl angewendet wird.
Für Ihr Beispiel wäre das erste Muster die erste sein passenden
Hide
Eintrag und das zweite Muster ist entwederHide
,Show
oder das Ende der Datei (vorausgesetzt , Sie wollen, dass letzte ausblenden Fall).Der erste reguläre Ausdruck ist einfach
/Hide/
. Die zweite Regex enthält einige interessante Teile.\(
und\)
erstellt eine entsprechende Gruppierung von Atomen\|
ist die ODER-Verknüpfung\%$
repräsentiert das Ende der DateiSobald wir unsere Bereiche definiert haben, wenden wir Ersatz durch ein Muster und eine Zeichenfolge an, wie Sie es normalerweise tun würden.
Bitte beachten Sie, dass der in diesem Beispiel verwendete reguläre Ausdruck sehr einfach ist. Sie sollten sicherstellen, dass Ihre Kennungen für den Anfang und das Ende des Bereichs die richtigen Bereiche erfassen.
quelle
Es sieht so aus, als ob dein böser Regex nicht böse genug war ... :-)
Suchbereich
Die Suche müsste folgendermaßen geändert werden:
Dies beinhaltet einige ungewöhnliche Dinge und so viele Klammern ... Mal sehen, was wir da drin haben:
Das Caret (
^
)Mit dem Caret wird der Zeilenanfang bezeichnet. Ich denke, wir sind mit diesem bereits vertraut.
Ein wichtiger Punkt, der
^
funktioniert nur als erstes Zeichen in Ihrem Muster. Nach dem wird es wörtlich genommen. Um einen Zeilenanfang in Ihren Ausdruck aufzunehmen, müssen Sie ihn verwenden\_^
. In unserer Situation brauchten wir das jedoch nicht.(Es gibt ein ähnliches Phänomen mit
$
und\_$
)Die erste und letzte Klammer (
\( ... \)
)Die erste und die letzte Klammer werden alleine verwendet, was bedeutet, dass alles, was darin erscheint, erfasst und in den Parameter gesetzt wird
\1
. Sie haben das bereits in Ihrem eigenen regulären Ausdruck verwendet, daher gehe ich davon aus, dass Sie auch mit diesem vertraut sind.Der zweite Satz in Klammern
Wie Sie vielleicht bemerken, gibt es einen zweiten Satz Klammern, gefolgt von einem Sternchen
\( ... \)*
. Das heißt, wir suchen nach dem, was beliebig oft passt. Dies ist die übliche Art, das Sternchen zu verwenden, daher sollten Sie damit vertraut sein.Der dritte Satz von Klammern, OR und
\_.
Ja, es gibt tatsächlich drei Klammern vor dem Wort
Show
. Dieser letzte Satz ist aus zwei Gründen erforderlich:\|
dem folgenden und dem folgenden@!
.In Bezug auf die OP-Operation sollten Sie bereits damit vertraut sein.
Die Reihenfolge spielt hier keine Rolle. Das
\
ist vor dem notwendig|
, um in vim zu arbeiten.Die Klammer um diesen Ausdruck ermöglicht es uns, dem Ausdruck durch etwas zu folgen . Hier die
@!
.Dieser ist viel weniger vertraut. Es bedeutet, wenn nicht übereinstimmend . Die Verwendung ist zwar nicht sehr einfach, aber Sie müssen diesem Ausdruck das folgen, was Sie extrahieren möchten, das nicht mit dem Ausdruck übereinstimmen sollte. Deshalb haben wir
\_.
hinter diesem Muster.Die
\_.
Mittel passen zu allem. Im Gegensatz zu der.
für sich, die nicht zum\n
Charakter passt . Mit anderen Worten, wir stimmen mit jedem Zeichen in einer beliebigen Anzahl von Zeilen überein, es sei denn, es stimmt mitShow
oder übereinHide
.Beachten Sie, dass die Klammern um diesen Ausdruck ebenso wichtig sind wie das Sternchen. Das Ganze macht es also wirklich möglich:
was bis zum nächsten aka übereinstimmen
Show
oderHide
Zeichen (beachten Sie, dass es würde auch passenShowing
,Shower
,HideMe
etc. sollten Sie verwenden können,\<
und\>
wenn es notwendig ist , das Wort genau übereinstimmen.)Randnotiz: Um in mehreren Zeilen zu suchen, können Sie auch das
\n
Zeichen im Muster verwenden. Es ist jedoch nicht so vielseitig als das\_.
Muster.SetFontSize 28
Jetzt muss der Abschnitt
SetFontSize 28
auch enthalten. Genau wie du es in deiner Regex getan hast. WennSetFontSize 28
in diesem Abschnitt kein angezeigt wird, wiederholen Sie die Suche im nächsten Abschnitt.Aufgrund der obigen Negation (die Übereinstimmung außer
Show
oderHide
) geht die Suche nicht zum nächsten Abschnitt über, wodurch das Risiko besteht, dass sie durcheinander gebracht wird.Ersatzteil
Der Ersatz ist genauso wie Sie ihn hatten:
Wir verwenden die Klammern in der Suche, damit das
\1
wie erwartet funktioniert.Vollständige Suche und Ersetzung
Die resultierenden Muster sehen folgendermaßen aus:
Das
\(Show\|Hide\)
sollte alle möglichen Header enthalten .Quellen
Regex für jedes Zeichen, einschließlich Zeilenumbruch (
\_.\{-}
)Suche nach Zeilen ohne Muster und andere hilfreiche Suchanfragen (
@!
)Vim-Dokumentation: pattern (
\_^
)quelle
()*
, meine Version Ihrer Antwort :%s/\v^Hide.*\n(\s+.*\n)*\s*SetFontSize\s+\zs28/16
.