Suchen und Ersetzen mit regulären Ausdrücken

Ich habe eine Datei mit einer Reihe von Benutzervorgaben. Ich möchte einen Teil des Textes ändern, habe aber Probleme Verwenden des folgenden Beispiels:

############################################################################### # Trackpad, mouse, keyboard, Bluetooth accessories, and input # ############################################################################### # Trackpad: enable tap to click for this user and for the login screen defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true 

Ich möchte # Trackpad: ... ersetzen mit running "Trackpad: ..."

Um das Problem zu lösen, habe ich mit einem Regex-Tester etwas gefunden:

/\n\n#\s(.*)/g 

Wenn ich versuche, dies in Vim zu verwenden, funktioniert es bei mir nicht:

:/\n\n#\s(.*)/running "\1"/g 

Ich denke, mein Problem besteht aus zwei spezifischen Fragen:

  1. Wie kann ich vermeiden, nach \n Zeichen zu suchen, und stattdessen sicherstellen, dass # nicht angezeigt wird am Ende der Suchgruppe?
  2. Wie kann ich Erfassungsgruppen effektiv verwenden?

Im Folgenden finden Sie einige gute Antworten. Es ist schwer, zwischen allen drei zu wählen, aber ich denke, die gewählte Antwort ist die genaueste für meine ursprüngliche Spezifikation. Ich empfehle Ihnen, alle drei Antworten mit der aktuellen Datei zu versuchen, um zu sehen, wie Sie mit ihnen umgehen.

Antwort

Nur um klar zu sein … Ich glaube, Sie haben darum gebeten, dass dies das Ergebnis der Substitution ist?

############################################################################### # Trackpad, mouse, keyboard, Bluetooth accessories, and input # ############################################################################### running "Trackpad: enable tap to click for this user and for the login screen" defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true 

In diesem Fall empfehle ich den folgenden Befehl:

:%s/\n\n#\s\+\(.*\)/^M^Mrunning "\1"/

Erläuterung des Musters

:s/PATTERN/REPLACEMENT/ ist der Ersatzbefehl . Das Prozentzeichen in :%s bewirkt, dass es für die gesamte Datei und nicht nur für die aktuelle Zeile funktioniert.

Die \n\n sagt, dass die interessierende Linie nach einer leeren Linie auftreten muss. Wenn Sie sich nicht um die vorhergehende Leerzeile kümmern würden, würde ^ ausreichen.

#\s\+ entspricht einem Hash Zeichen gefolgt von einem oder mehreren Leerzeichen. \(.*\) erfasst den gesamten nachfolgenden Text in der Zeile.

Erläuterung des Ersatztextes

^M^M fügt zwei Zeilenenden ein, um die im Muster vorhandenen \n\n zu ersetzen. Andernfalls wird der Text an das Zeilenende verschoben vor jedem Leerzeichen. Um jedes ^M einzugeben, drücken Sie Strg-V Strg-M .

Fügen Sie dann die Zeichenfolge running ein, gefolgt von dem, was in Klammern in doppelten Anführungszeichen steht.

Kommentare

  • Ich kann Ihre Antwort nicht bearbeiten, aber ich glaube, Sie meinten :%s/\v\n\n#\s+(.*)/^M^Mrunning "\1"/ (fügte die “ Magie flag). Es ist wirklich schwer zu wählen Eine korrekte Antwort auf meine ursprüngliche Frage, aber ich bin der Meinung, dass diese Antwort meiner ursprünglich erwarteten Antwort am nächsten kommt. Es ist auch das einzige, das in der gesamten Datei funktioniert, ohne dass ein Bereich ausgewählt werden muss.
  • IIRC Sie können \r anstelle von , um neue Zeilen zu erhalten?

Antwort

Ich würde so etwas wie Folgendes verwenden:

:s/^#\s\+\(.\{-}\):/running "\1":/ 
  • ^# entspricht dem verankerten Zeichen # am Anfang der Zeile (dies beantwortet Frage 1)
  • \s\+, um ein oder mehrere Leerzeichen einmal oder mehrmals zuzuordnen
  • \(, um eine Gruppe zu starten (dies beantwortet Frage 2)
  • .\{-}\, um einem beliebigen Zeichen 0 oder mehrmals in a zu entsprechen nicht gieriger Weg ; Dies unterscheidet sich von .* darin, dass versucht wird, so wenig wie möglich und nicht so viel wie möglich zusammenzubringen. Fügen Sie dem Kommentar ein Zeichen : hinzu, um festzustellen, warum dies wichtig ist.
  • \), um die Untergruppe zu beenden.
  • : stimmt mit einem Literal überein :

Wir ersetzen dies dann durch den Text Sie möchten und verwenden \1, um auf die Gruppe zu verweisen, die wir erfasst haben.

Ich habe etwas mit gefunden Ein Regex-Tester

Die Syntax für reguläre Ausdrücke ähnelt der Wiki-Syntax: Es gibt eine Reihe von Syntaxen, die alle auf einen Blick gleich aussehen, keine von ihnen ist offensichtlich besser als alle anderen, aber es gibt viele Unterschiede.

Heutzutage sind die sogenannten „Perl-kompatiblen“ regulären Ausdrücke in den meisten Sprachen de facto die Standardeinstellung, reguläre Vim-Ausdrücke jedoch nicht kompatibel mit Perl-kompatiblen Ausdrücken! Die Vim-Regexp-Syntax geht mindestens auf die „70“ zurück, als Perl noch nicht einmal in der Nähe war.

Sie können dies bei den Untergruppen sehen, in denen Sie \( und nicht ( (dies ist kompatibel mit der „grundlegenden“ POSIX-Syntax, jedoch nicht mit der allgemeineren „erweiterten“ POSIX-Syntax oder Perl-Syntax).Sie können dies steuern, indem Sie das Flag \v in einem Muster hinzufügen (siehe :help /\v für Details), dies macht es „kompatibler“, aber nicht vollständig (Sie müssen beispielsweise .{-} für nicht gierige Übereinstimmungen verwenden)

Dies könnte erklären, warum die Verwendung eines „Regex-Testers“ fast, aber nicht ganz funktioniert.

http://www.vimregex.com/ als gute Übersicht / Cheatsheet von Vim-Regexps.

Kommentare

  • Tolle Antwort, besonders mit warum Regex! = Regex. Das Suchen und Ersetzen ist ‚ etwas schwierig, da der Kommentar möglicherweise ein : enthält oder nicht. Weitere Informationen finden Sie in der vollständigen Datei. github.com/squarefrog/dotfiles/blob/master/osx/…

Antwort

Sie können:

  • nach Zeilen suchen, die nicht enden in #: :/[^#]$/
  • Ersetzen Sie #\s(.*) zu Beginn von die Zeile: s/\v^#\s(.*)/running "\1"/

Um Gruppen zu verwenden, müssen Sie entweder:

  • die Klammern verlassen, damit Sie werden Teil der Regex-Syntax: \(.*\) oder
  • verwenden „magic“ von Beginnen Sie den Ausdruck mit \v: s/\v...

Kombinieren Sie ihn:

:/[^#]$/s/\v^#\s(.*)/running "\1"/ 

Kommentare

  • Dies funktioniert hervorragend, danke für die Erklärung, was die Tags bedeuten, und nicht nur für den Text, den ich brauchte Schreiben Sie.
  • Vielen Dank, dass Sie klargestellt haben, dass die Klammern t haben o maskiert werden, um Teil der Regex-Syntax zu werden. Ich hatte immer ein Problem mit Regex-Gruppen, um sie zum Laufen zu bringen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.