Come posso filtrare un file per le righe che contengono una stringa in Sublime Text 2?


74

Voglio filtrare un file che sto modificando in Sublime Text 2 per le righe che contengono una determinata stringa, se possibile includendo espressioni regolari.

Considera il seguente file:

foo bar
baz
qux
quuux baz

Se filtrato per ba, il risultato dovrebbe essere:

foo bar
baz
quuux baz

Come posso fare ciò?

Risposte:


87

Sublime Text 2 è un editor estensibile con un'API Python . Puoi creare nuovi comandi (chiamati Plugin ) e renderli disponibili dall'interfaccia utente.

Aggiunta del plug-in TextCommand di filtro di base

In Sublime Text 2, seleziona Strumenti »Nuovo plug-in e inserisci il testo seguente:

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)

Salva come filter.pyin~/Library/Application Support/Sublime Text 2/Packages/User

Integrazione con l'interfaccia utente

Per aggiungere questo plugin al menu Modifica , seleziona Preferenze ... »Sfoglia pacchetti e apri la Usercartella. Se un file chiamato Main.sublime-menunon esiste, crealo. Aggiungi o imposta il seguente testo in quel file:

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

Ciò inserirà la filterchiamata di comando (essenzialmente, filterviene trasformata in FilterCommand().run(…)per la chiamata del plug-in e Filtro per l'etichetta del menu) proprio sotto il wrapcomando. Vedere il passaggio 11 qui per una spiegazione più dettagliata del perché.

Per assegnare una scorciatoia da tastiera, apri e modifica il file Default (OSX).sublime-keymapsu OS X o l'equivalente per altri sistemi e inserisci quanto segue:

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

Questo assegnerà il collegamento Fa questo comando.


Per visualizzare il comando nella Tavolozza comandi , è necessario creare un file denominato Default.sublime-commands(o modificarne uno esistente) nella Usercartella. La sintassi è simile al file di menu appena modificato:

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

Le voci multiple (racchiuse tra parentesi graffe) devono essere separate da virgole.

 Schermate di integrazione del comportamento e dell'interfaccia utente

Il comando, come implementato, filtrerà tutte le linee che fanno parte di una selezione (le linee intere, non solo le parti selezionate) o, se non esiste alcuna selezione, l'intero buffer, per una sottostringa immessa nel campo di input ( il default è il - forse inutile multi-line - appunti) dopo l'attivazione del comando. Può essere facilmente esteso, ad esempio, per supportare espressioni regolari o lasciare solo righe che non corrispondono a una determinata espressione.

Elemento del menu

Comando nel menu

Comanda l'inserimento della palette

Comando con un'etichetta diversa nella Tavolozza dei comandi

editore

L'utente inserisce il testo con cui filtrare il file

Risultato dopo aver eseguito il comando

Aggiunta del supporto per le espressioni regolari

Per aggiungere supporto per le espressioni regolari, utilizzare invece i seguenti script e frammenti:

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"
    }
]  

Un secondo comando di plugin, Filter Using Regular Expression sarà aggiunto sotto la voce del menu Filter .

Default.sublime-commands:

[
    { "caption": "Filter Lines in File", "command": "filter" },
    { "caption": "Filter Lines in File Using Regular Expression", "command": "filter_using_regular_expression" }
]

2
Non vuoi pubblicarlo un giorno come pacchetto?
slhck,

1
@slhck Qualcuno l'ha già fatto (con l'attribuzione appropriata), vedi la risposta di NovicePhysicist. Da quello che ho letto nel codice, è stato migliorato un po 'anche su questa risposta.
Daniel Beck

Bene, non me ne sono accorto!
slhck,

Qual è il tema che hai con SublimeText che dà quei bei colori? O sta semplicemente cambiando il colore della finestra?
pal4life

1
@ pal4life: si chiama Solarized (Light) . Penso che Sublime Text sia persino fornito con esso. Potrei averne installato uno alternativo, quindi i colori potrebbero non corrispondere esattamente. Le schermate si trovano su OS X, quindi è qui che provengono il bordo della finestra e la barra del titolo.
Daniel Beck

83

C'è anche un algoritmo di filtraggio delle linee di un uomo povero (o è pigro?):

  1. Seleziona la stringa di interesse
  2. Premi Alt+ F3per accedere alla modalità multi-cursore su tutte le occorrenze
  3. Premi Control+ Lper selezionare l'intera linea (su ogni linea del cursore)
  4. Copia e incolla la selezione in un altro buffer

2
Questa è praticamente la soluzione più semplice. Bravo!
Gillytech,

Grazie! Preferisco non dover installare / apprendere un altro plugin il più possibile - Alt + F3 è nella mia memoria muscolare, quindi la soluzione di cui sopra in realtà non è poi così inverosimile per me.
Olof Bjarnason,

Puoi sostituire i passaggi 3 e 4 con un solo passaggio: Ctrl + L.
Andres Riofrio,

1
Bella soluzione semplice! Vorrei sostituire il passaggio 3 da Ctrl-L a Home, Maiusc-Fine Quindi non ci sono linee vuote tra le occorrenze.
jslap,

4
Questo ha cambiato la mia vita in meglio. Niente sarà mai più lo stesso.
Shawson,

49

Esiste ora un plug-in per le linee di filtro: https://github.com/davidpeckham/FilterLines
Permette il filtro e la piegatura del codice in base a stringhe o espressioni regolari.


Plugin per filtri di testo sublime di David Peckham


4
Ho appena installato questo plugin - PERFETTO per il lavoro. Prende un file esistente, consente di inserire una frase di filtro e inserisce i risultati in una nuova scheda.
Nick,

4
D'accordo, fino ad ora ho sempre e solo sognato di avere questo tipo di funzionalità nel mio editor di testo.
Michael12345,

1
Questo plugin è davvero fantastico!
Devid

Sono venuto qui perché un collega ha parlato di "Keep Lines" per emacs e di quanto sia utile. Non sapevo nemmeno che avessi bisogno di questo plugin, lo adoro!
brandon927,

14

È possibile utilizzare le funzionalità integrate di Sublime per eseguire questa operazione con un numero di tasti compreso tra 3 e 7 (escluso il regex da abbinare).

Passaggio 1: selezionare più linee corrispondenti

Opzione 1: per selezionare più linee di una sottostringa

  1. Seleziona la stringa di interesse.
  2. Premi Alt+ F3per selezionare più volte tutte le occorrenze.
  3. Premi Ctrl+ L(espandi selezione in linea).

Opzione 2: per selezionare più linee in corrispondenza di una regexp

  1. Premi Ctrl+ Fper aprire il cassetto Trova.
  2. Assicurati che la corrispondenza delle espressioni regolari sia abilitata ( Alt+ Rper attivare / disattivare).
  3. Digita l'espressione regolare.
  4. Premi Alt+ Enterper selezionare più tutte le partite.
  5. Premi Ctrl+ L(espandi selezione in linea).

Passaggio 2: fai qualcosa con quelle righe

Opzione 1: sbarazzarsi di tutte le linee che non sono selezionate

  1. Premi Ctrl+ Cper copiare.
  2. Premi Ctrl+ Aper selezionare tutto.
  3. Premi Ctrl+ Vper sostituire la selezione con le linee corrispondenti.

Opzione 2: per sbarazzarsi di tutte le linee che vengono selezionati

  1. Premi Ctrl+ Shift+ K(Elimina riga).

Opzione 3: estrarre le linee selezionate in un nuovo file

  1. Premi Ctrl+ Cper copiare.
  2. Premi Ctrl+ Nper aprire un nuovo file.
  3. Premi Ctrl+ Vper incollare.

Questo è un eccellente elenco di comandi!
Chustar,

Super, ma c'è modo di rimuovere le righe vuote dopo l'incollaggio?
Sergey Senkov

1
@SergeySenkov Certo! (1) Premi Ctrl + F per aprire il cassetto Trova. (2) Assicurati che la corrispondenza delle espressioni regolari sia abilitata (Alt + R per attivare / disattivare). (3) Digita "\ n \ n +" (corrisponde a due o più newline consecutive). (4) Premi Alt + Invio per selezionare più partite tutte. (5) Premi Invio per sostituire tutte le partite con una nuova riga.
Andres Riofrio,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.