Wie kann ich in Sublime Text 2 eine Datei nach Zeilen filtern, die eine Zeichenfolge enthalten?

74

Ich möchte eine Datei, die ich in Sublime Text 2 bearbeite, nach Zeilen filtern, die eine bestimmte Zeichenfolge enthalten, wenn möglich einschließlich regulärer Ausdrücke.

Betrachten Sie die folgende Datei:

foo bar
baz
qux
quuux baz

Wenn nach gefiltert wird ba, sollte das Ergebnis sein:

foo bar
baz
quuux baz

Wie kann ich das machen?

Daniel Beck
quelle

Antworten:

87

Sublime Text 2 ist ein erweiterbarer Editor mit einer Python-API . Sie können neue Befehle (sogenannte Plugins ) erstellen und über die Benutzeroberfläche verfügbar machen.

Hinzufügen des TextCommand-Plugins für die Grundfilterung

Wählen Sie in Sublime Text 2 Extras »Neues Plugin und geben Sie den folgenden Text ein:

import sublime, sublime_plugin

def filter(v, e, needle):
    # get non-empty selections
    regions = [s for s in v.sel() if not s.empty()]

    # if there's no non-empty selection, filter the whole document
    if len(regions) == 0:
        regions = [ sublime.Region(0, v.size()) ]

    for region in reversed(regions):
        lines = v.split_by_newlines(region)

        for line in reversed(lines):
            if not needle in v.substr(line):
                v.erase(e, v.full_line(line))

class FilterCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        def done(needle):
            e = self.view.begin_edit()
            filter(self.view, e, needle)
            self.view.end_edit(e)

        cb = sublime.get_clipboard()
        sublime.active_window().show_input_panel("Filter file for lines containing: ", cb, done, None, None)

Speichern wie filter.pyin~/Library/Application Support/Sublime Text 2/Packages/User

Integration mit der Benutzeroberfläche

Um dieses Plugin zum Menü Bearbeiten hinzuzufügen , wählen Sie Einstellungen… »Pakete durchsuchen und öffnen Sie den UserOrdner. Wenn eine aufgerufene Datei Main.sublime-menunicht existiert, erstellen Sie sie. Fügen Sie dieser Datei den folgenden Text hinzu oder legen Sie ihn fest:

[
    {
        "id": "edit",
        "children":
        [
            {"id": "wrap"},
            { "command": "filter" }
        ]
    }
]

Dadurch wird der filterBefehlsaufruf (der im Wesentlichen filterin FilterCommand().run(…)für den Plug-in-Aufruf und Filter für die Menübeschriftung umgewandelt wird) direkt unter dem wrapBefehl eingefügt. In Schritt 11 finden Sie eine ausführlichere Erklärung, warum dies so ist.

Um eine Tastenkombination zuzuweisen, öffnen und bearbeiten Sie die Datei Default (OSX).sublime-keymapunter OS X oder einer Entsprechung für andere Systeme und geben Sie Folgendes ein:

[  
    {   
        "keys": ["ctrl+shift+f"], "command": "filter"
    }  
]  

Dadurch wird die Verknüpfung Fzu diesem Befehl zugewiesen .


Damit der Befehl in der Befehlspalette angezeigt wird , müssen Sie eine Datei mit dem Namen Default.sublime-commands(oder einer vorhandenen) im UserOrdner erstellen . Die Syntax ähnelt der soeben bearbeiteten Menüdatei:

[
    { "caption": "Filter Lines in File", "command": "filter" }
]

Mehrere Einträge (in geschweiften Klammern) müssen durch Kommas getrennt werden.

 Screenshots zu Verhalten und UI-Integration

Der Befehl filtert, wie implementiert, alle Zeilen, die Teil einer Auswahl sind (die gesamten Zeilen, nicht nur die ausgewählten Teile), oder, falls keine Auswahl vorhanden ist, den gesamten Puffer für eine Teilzeichenfolge, die in das Eingabefeld eingegeben wird ( Standard ist die - möglicherweise unbrauchbare - mehrzeilige Zwischenablage, nachdem der Befehl ausgelöst wurde. Es kann leicht erweitert werden, um zB reguläre Ausdrücke zu unterstützen oder nur Zeilen zu belassen, die nicht mit einem bestimmten Ausdruck übereinstimmen.

Menüpunkt

Befehl im Menü

Befehlspaletteneintrag

Befehl mit anderer Bezeichnung in der Befehlspalette

Editor

Der Benutzer gibt Text ein, mit dem die Datei gefiltert werden soll

Ergebnis nach Ausführung des Befehls

Unterstützung für reguläre Ausdrücke hinzufügen

Verwenden Sie stattdessen die folgenden Skripts und Snippets, um Unterstützung für reguläre Ausdrücke hinzuzufügen:

filter.py:

import sublime, sublime_plugin, re

def matches(needle, haystack, is_re):
    if is_re:
        return re.match(needle, haystack)
    else:
        return (needle in haystack)

def filter(v, e, needle, is_re = False):
    # get non-empty selections
    regions = [s for s in v.sel() if not s.empty()]

    # if there's no non-empty selection, filter the whole document
    if len(regions) == 0:
        regions = [ sublime.Region(0, v.size()) ]

    for region in reversed(regions):
        lines = v.split_by_newlines(region)

        for line in reversed(lines):

            if not matches(needle, v.substr(line), is_re):
                v.erase(e, v.full_line(line))

class FilterCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        def done(needle):
            e = self.view.begin_edit()
            filter(self.view, e, needle)
            self.view.end_edit(e)

        cb = sublime.get_clipboard()
        sublime.active_window().show_input_panel("Filter file for lines containing: ", cb, done, None, None)

class FilterUsingRegularExpressionCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        def done(needle):
            e = self.view.begin_edit()
            filter(self.view, e, needle, True)
            self.view.end_edit(e)

        cb = sublime.get_clipboard()
        sublime.active_window().show_input_panel("Filter file for lines matching: ", cb, done, None, None)

Main.sublime-menu:

[
    {
        "id": "edit",
        "children":
        [
            {"id": "wrap"},
            { "command": "filter" },
            { "command": "filter_using_regular_expression" }
        ]
    }
]

Default (OSX).sublime-keymap:

[  
    {   
        "keys": ["ctrl+shift+f"], "command": "filter"
    },
    {
        "keys": ["ctrl+shift+option+f"], "command": "filter_using_regular_expression"
    }
]  

Ein zweiter Plugin-Befehl, Filter Using Regular Expression, wird unter dem Menüeintrag Filter hinzugefügt .

Default.sublime-commands:

[
    { "caption": "Filter Lines in File", "command": "filter" },
    { "caption": "Filter Lines in File Using Regular Expression", "command": "filter_using_regular_expression" }
]
Daniel Beck
quelle
2
Möchten Sie dies nicht eines Tages als Paket veröffentlichen?
Slhck
1
@slhck Jemand hat dies bereits getan (mit entsprechender Zuschreibung), siehe Antwort von NovicePhysicist. Nach dem, was ich im Code gelesen habe, hat sich auch diese Antwort erheblich verbessert.
Daniel Beck
Cool, das habe ich nicht gemerkt!
Slhck
Was ist das Thema, das Sie mit dem SublimeText haben, das diese schönen Farben gibt? Oder ändert es nur die Fensterfarbe?
Pal4life
1
@ pal4life: Es heißt Solarized (Light) . Ich denke, Sublime Text wird sogar mitgeliefert. Möglicherweise habe ich jedoch eine Alternative installiert, sodass die Farben möglicherweise nicht genau übereinstimmen. Screenshots sind unter OS X zu sehen, daher stammen der Fensterrand und die Titelleiste von dort.
Daniel Beck
83

Es gibt auch einen Zeilenfilteralgorithmus für Arme (oder ist er faul?):

  1. Wählen Sie die gewünschte Zeichenfolge aus
  2. Drücken Sie Alt+ F3, um bei jedem Auftreten in den Multi-Cursor-Modus zu wechseln
  3. Drücken Sie Control+ L, um die gesamte Zeile (in jeder Cursorzeile) auszuwählen.
  4. Auswahl kopieren und in einen anderen Puffer einfügen
Olof Bjarnason
quelle
2
Dies ist so ziemlich die einfachste Lösung. Bravo!
gillytech
Danke! Ich ziehe es vor, nicht so oft wie möglich ein anderes Plugin installieren / lernen zu müssen - Alt + F3 befindet sich in meinem Muskelgedächtnis, daher ist die obige Lösung für mich eigentlich nicht so weit hergeholt.
Olof Bjarnason
Sie können die Schritte 3 und 4 durch einen einzelnen Schritt ersetzen: Strg + L.
Andres Riofrio
1
Schöne einfache Lösung! Ich würde Schritt 3 von Strg-L nach Home, Shift-End ersetzen. Es gibt also keine Leerzeilen zwischen den Ereignissen.
Jslap
4
Dies hat mein Leben zum Besseren verändert. Nichts wird jemals wieder so sein wie vorher.
Shawson
49

Es gibt jetzt ein Plugin zum Filtern von Zeilen: https://github.com/davidpeckham/FilterLines
Es ermöglicht das Filtern und Falten von Code basierend auf Zeichenfolgen oder regulären Ausdrücken.


Sublime Text Filter Plugin von David Peckham

AllanLRH
quelle
4
Habe gerade dieses Plugin installiert - PERFECT für den Job. Nimmt eine vorhandene Datei, lässt Sie eine Filterphrase eingeben und legt die Ergebnisse in einer neuen Registerkarte ab.
Nick
4
Einverstanden, bis jetzt habe ich nur davon geträumt, diese Art von Funktionalität in meinem Texteditor zu haben.
Michael12345
1
Dieses Plugin ist wirklich großartig!
Devid
Kam hierher, weil ein Mitarbeiter etwas über "Keep Lines" für Emacs erwähnt hat und wie nützlich es ist. Wusste gar nicht, dass ich dieses Plugin brauche, liebe es!
brandon927
14

Sie können die in Sublime integrierten Funktionen verwenden, um dies in 3 bis 7 Tastenanschlägen zu tun (ohne die zu vergleichende Regex).

Schritt 1: Mehrfachauswahl aller übereinstimmenden Zeilen

Option 1: Mehrfachauswahl aller Zeilen, die eine Teilzeichenfolge enthalten

  1. Wählen Sie die gewünschte Zeichenfolge aus.
  2. Drücken Sie Alt+ F3, um alle Vorkommen auszuwählen.
  3. Drücken Sie Ctrl+ L(Auswahl auf Linie erweitern).

Option 2: Mehrfachauswahl aller Zeilen, die einem regulären Ausdruck entsprechen

  1. Drücken Sie Ctrl+ F, um die Find-Schublade zu öffnen.
  2. Stellen Sie sicher, dass die Übereinstimmung mit regulären Ausdrücken aktiviert ist ( Alt+ Rumschalten).
  3. Geben Sie den regulären Ausdruck ein.
  4. Drücken Sie Alt+ Enter, um alle Übereinstimmungen auszuwählen.
  5. Drücken Sie Ctrl+ L(Auswahl auf Linie erweitern).

Schritt 2: Machen Sie etwas mit diesen Zeilen

Option 1: Entfernen aller nicht ausgewählten Zeilen

  1. Hit Ctrl+ Czu kopieren.
  2. Drücken Sie Ctrl+ A, um alle auszuwählen.
  3. Drücken Sie Ctrl+ V, um die Auswahl durch die entsprechenden Zeilen zu ersetzen.

Option 2: Um alle Linien loszuwerden, sind ausgewählt

  1. Drücken Sie Ctrl+ Shift+ K(Zeile löschen).

Option 3: Extrahieren ausgewählter Zeilen in eine neue Datei

  1. Hit Ctrl+ Czu kopieren.
  2. Drücken Sie Ctrl+ N, um eine neue Datei zu öffnen.
  3. Drücken Sie Ctrl+, Vum einzufügen.
Andres Riofrio
quelle
Dies ist eine hervorragende Liste von Befehlen!
Chustar
Super, aber gibt es eine Möglichkeit, Leerzeilen nach dem Einfügen zu entfernen?
Sergey Senkov
1
@SergeySenkov Sicher! (1) Drücken Sie Strg + F, um die Schublade Suchen zu öffnen. (2) Stellen Sie sicher, dass die Übereinstimmung mit regulären Ausdrücken aktiviert ist (Alt + R zum Umschalten). (3) Geben Sie "\ n \ n +" ein (entspricht zwei oder mehr aufeinanderfolgenden Zeilenumbrüchen). (4) Drücken Sie Alt + Eingabetaste, um alle Übereinstimmungen auszuwählen. (5) Drücken Sie die Eingabetaste, um alle Übereinstimmungen durch eine einzelne neue Zeile zu ersetzen.
Andres Riofrio