¿Cómo puedo filtrar un archivo por líneas que contienen una cadena en Sublime Text 2?

74

Quiero filtrar un archivo que estoy editando en Sublime Text 2 para que las líneas contengan una cadena determinada, si es posible, incluidas las expresiones regulares.

Considere el siguiente archivo:

foo bar
baz
qux
quuux baz

Cuando se filtra por ba, el resultado debe ser:

foo bar
baz
quuux baz

¿Cómo puedo hacer eso?

Daniel Beck
fuente

Respuestas:

87

Sublime Text 2 es un editor extensible con una API de Python . Puede crear nuevos comandos (llamados complementos ) y ponerlos a disposición desde la interfaz de usuario.

Agregar un complemento de filtrado de texto básico a TextCommand

En Sublime Text 2, seleccione Tools »New Plugin e ingrese el siguiente texto:

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)

Guardar como filter.pyen~/Library/Application Support/Sublime Text 2/Packages/User

Integración con UI

Para agregar este complemento al menú Editar , seleccione Preferencias ... »Buscar paquetes y abra la Usercarpeta. Si Main.sublime-menuno existe un archivo llamado , créelo. Agregue o establezca el siguiente texto en ese archivo:

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

Esto insertará la filterllamada al comando (esencialmente, filterse transforma FilterCommand().run(…)para la llamada del complemento y Filtro para la etiqueta del menú) justo debajo del wrapcomando. Vea el paso 11 aquí para obtener una explicación más detallada de por qué.

Para asignar un atajo de teclado, abra y edite el archivo Default (OSX).sublime-keymapen OS X, o el equivalente para otros sistemas, e ingrese lo siguiente:

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

Esto asignará el acceso directo Fa este comando.


Para que el comando aparezca en la Paleta de comandos , debe crear un archivo llamado Default.sublime-commands(o editar uno existente) en la Usercarpeta. La sintaxis es similar al archivo de menú que acaba de editar:

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

Las entradas múltiples (encerradas entre llaves) deben estar separadas por comas.

 Capturas de pantalla de comportamiento e integración de UI

El comando, tal como se implementa, filtrará todas las líneas que forman parte de una selección (las líneas completas, no solo las partes seleccionadas) o, si no existe una selección, el búfer completo, para una subcadena que se ingresa en el campo de entrada ( el valor predeterminado es el portapapeles de varias líneas, posiblemente inútil, después de que se active el comando. Se puede ampliar fácilmente para, por ejemplo, admitir expresiones regulares, o solo dejar líneas que no coincidan con una determinada expresión.

Opción del menú

Comando en el menú

Entrada de paleta de comandos

Comando con etiqueta diferente en la paleta de comandos

Editor

El usuario ingresa texto para filtrar el archivo con

Resultado después de ejecutar el comando

Agregar soporte para expresiones regulares

Para agregar soporte para expresiones regulares, use los siguientes scripts y fragmentos en su lugar:

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

Se agregará un segundo comando de complemento, Filtro con expresión regular , debajo de la entrada del menú Filtro .

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
fuente
2
¿No quieres publicar esto como un paquete algún día?
slhck
1
@slhck Alguien ya lo hizo (con la atribución adecuada), vea la respuesta de NovicePhysicist. Por lo que leí en el código, también se mejoró bastante esta respuesta.
Daniel Beck
¡Genial, no me di cuenta de eso!
slhck
¿Cuál es ese tema que tienes con el SublimeText que le da esos bonitos colores? ¿O simplemente está cambiando el color de la ventana?
pal4life
1
@ pal4life: se llama Solarized (Light) . Creo que Sublime Text incluso se envía con él. Sin embargo, podría haber instalado una alternativa, por lo que los colores podrían no coincidir exactamente. Las capturas de pantalla están en OS X, así que de ahí son el borde de la ventana y la barra de título.
Daniel Beck
83

También hay un algoritmo de filtrado de línea de un hombre pobre (¿o es vago?):

  1. Seleccionar cadena de interés
  2. Presione Alt+ F3para ir al modo de cursor múltiple en todas las ocurrencias
  3. Presione Control+ Lpara seleccionar la línea completa (en cada línea del cursor)
  4. Copiar y pegar selección a otro búfer
Olof Bjarnason
fuente
2
Esta es prácticamente la solución más simple. ¡Bravo!
gillytech 01 de
¡Gracias! Prefiero no tener que instalar / aprender otro complemento tanto como sea posible: Alt + F3 está en mi memoria muscular, por lo que la solución anterior no es tan descabellada para mí.
Olof Bjarnason
Puede reemplazar los pasos 3 y 4 con un solo paso: Ctrl + L.
Andres Riofrio
1
Buena solución simple! Reemplazaría el paso 3 de Ctrl-L a Inicio, Shift-End Así que no hay líneas vacías entre las ocurrencias.
jslap
44
Esto cambió mi vida para mejor. Nada será lo mismo otra vez.
Shawson
49

Ahora hay un complemento para filtrar líneas: https://github.com/davidpeckham/FilterLines
Permite el filtrado y el plegado de código en función de cadenas o expresiones regulares.


Sublime Text Filter Plugin por David Peckham

AllanLRH
fuente
44
Acabo de instalar este complemento - PERFECTO para el trabajo. Toma un archivo existente, le permite ingresar una frase de filtro y coloca los resultados en una nueva pestaña.
Nick
44
De acuerdo, hasta ahora solo había soñado con tener este tipo de funcionalidad en mi editor de texto.
Michael12345
1
¡Este complemento es realmente increíble!
Devid
Vine aquí porque un compañero de trabajo mencionó algo sobre "Keep Lines" para emacs y lo útil que es. Ni siquiera sabía que necesitaba este complemento, ¡me encanta!
brandon927
14

Puede usar las capacidades integradas de Sublime para hacer esto en 3 a 7 pulsaciones de teclas (sin incluir la expresión regular que se va a combinar).

Paso 1: seleccione varias líneas coincidentes

Opción 1: para seleccionar múltiples todas las líneas que contienen una subcadena

  1. Seleccione la cadena de interés.
  2. Presiona Alt+ F3para seleccionar múltiples todas las ocurrencias.
  3. Hit Ctrl+ L(Expandir selección a línea).

Opción 2: para seleccionar múltiples todas las líneas que coinciden con una expresión regular

  1. Presiona Ctrl+ Fpara abrir el cajón Buscar.
  2. Asegúrese de que la coincidencia de expresiones regulares esté habilitada ( Alt+ Rpara alternar).
  3. Escriba la expresión regular.
  4. Presiona Alt+ Enterpara seleccionar todas las coincidencias.
  5. Hit Ctrl+ L(Expandir selección a línea).

Paso 2: haz algo con esas líneas

Opción 1: eliminar todas las líneas que no están seleccionadas

  1. Presiona Ctrl+ Cpara copiar.
  2. Presiona Ctrl+ Apara seleccionar todo.
  3. Presione Ctrl+ Vpara reemplazar la selección con las líneas coincidentes.

Opción 2: Para deshacerse de todas las líneas que se seleccionan

  1. Hit Ctrl+ Shift+ K(Eliminar línea).

Opción 3: extraer líneas seleccionadas a un nuevo archivo

  1. Presiona Ctrl+ Cpara copiar.
  2. Presiona Ctrl+ Npara abrir un nuevo archivo.
  3. Presiona Ctrl+ Vpara pegar.
Andres Riofrio
fuente
Esta es una excelente lista de comandos!
chustar
Super, pero ¿hay alguna forma de eliminar líneas en blanco después de pegar?
Sergey Senkov
1
@SergeySenkov ¡Seguro! (1) Presione Ctrl + F para abrir el cajón Buscar. (2) Asegúrese de que la coincidencia de expresiones regulares esté habilitada (Alt + R para alternar). (3) Escriba "\ n \ n +" (coincide con dos o más líneas nuevas consecutivas). (4) Presiona Alt + Enter para seleccionar todas las coincidencias. (5) Presiona Enter para reemplazar todas las coincidencias con una nueva línea.
Andres Riofrio