如何在Sublime Text 2中过滤包含字符串的行的文件?


72

我想过滤我正在Sublime Text 2中编辑的文件,因为行包含某个字符串,如果可能的话包括正则表达式。

考虑以下文件:

foo bar
baz
qux
quuux baz

过滤时 ba,结果应该是:

foo bar
baz
quuux baz

我怎样才能做到这一点?

Answers:


87

Sublime Text 2是一个带有的可扩展编辑器 Python API 。您可以创建新命令(称为 插件 )并从UI中获取它们。

添加基本​​过滤TextCommand插件

在Sublime Text 2中,选择 工具»新插件 并输入以下文本:

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)

另存为 filter.py~/Library/Application Support/Sublime Text 2/Packages/User

与UI集成

要将此插件添加到 编辑 菜单,选择 首选项...»浏览包 并打开 User 夹。如果一个文件叫 Main.sublime-menu 不存在,创造它。在该文件中添加或设置以下文本:

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

这将插入 filter 命令调用(基本上, filter 变成了 FilterCommand().run(…) 对于插件调用和 过滤 对于菜单标签)就在下方 wrap 命令。看到 这里是第11步 更详细的解释为什么会这样。

要分配键盘快捷键,请打开并编辑该文件 Default (OSX).sublime-keymap 在OS X上,或其他系统的等效项,并输入以下内容:

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

这将分配快捷方式 ^ F 这个命令。


使命令显示在 命令调色板 ,您需要创建一个名为的文件 Default.sublime-commands (或编辑现有的) User 夹。语法类似于刚刚编辑的菜单文件:

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

多个条目(用大括号括起来)需要用逗号分隔。

行为和UI集成截图

执行的命令将过滤作为选择的一部分的所有行(整行,而不仅仅是选定的部分),或者,如果不存在选择,则过滤整个缓冲区,用于输入到输入字段的子字符串(触发命令后,default是 - 可能无用的多行 - 剪贴板。它可以很容易地扩展到例如支持正则表达式,或只留下行 匹配某个表达式。

菜单项

Command in menu

命令调色板条目

Command with different label in Commands Palette

编辑

User entering text to filter file with

Result after executing the command

添加对正则表达式的支持

要添加对正则表达式的支持,请使用以下脚本和代码段:

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

第二个插件命令, 使用正则表达式过滤 将在下面添加 过滤 菜单条目。

Default.sublime-commands

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

2
你不想有一天将它作为包发布吗?
slhck

1
@slhck某人已经做过(有适当的归属),请参阅NovicePhysicist的回答。从我在代码中看到的内容来看,这个答案也得到了相当多的改进。
Daniel Beck

很酷,我没注意到!
slhck

SublimeText的主题是什么,它提供了漂亮的颜色?或者只是改变窗口颜色?
pal4life

1
@ pal4life:这叫做 日晒(光) 。我认为Sublime Text甚至附带它。我可能已经安装了另一个,所以颜色可能不完全匹配。屏幕截图位于OS X上,因此窗口边框和标题栏位于此处。
Daniel Beck

77

还有一个 穷人的线路过滤算法 (或者它是懒惰的?):

  1. 选择 感兴趣的字符串
  2. 击中 Alt键 + F3 在所有事件中进入多光标模式
  3. 击中 控制 + 大号 选择整行(在每个光标行上)
  4. 复制粘贴选择到另一个缓冲区

1
这是最简单的解决方案。好样的!
gillytech

谢谢!我不想尽可能多地安装/学习另一个插件 - Alt + F3在我的肌肉记忆中,所以上面的解决方案对我来说实际上并不是那么遥远。
Olof Bjarnason

您可以用一步替换步骤3和4:Ctrl + L.
Andres Riofrio

1
简单的解决方案!我会将步骤3从Ctrl-L替换为Home,Shift-End所以在出现之间没有空行。
jslap

4
这改变了我的生活。什么都不会再一样了。
Shawson

46

现在有一个 插入 过滤线: https://github.com/davidpeckham/FilterLines
它允许基于字符串或正则表达式进行过滤和代码折叠。


Sublime Text Filter Plugin by David Peckham


4
刚刚安装了这个插件 - 完美的工作。使用现有文件,您可以输入过滤短语并将结果放入新选项卡中。
Nick

4
同意,直到现在我才梦想在我的文本编辑器中拥有这种功能。
Michael12345

1
这个插件非常棒!
Devid

来到这里是因为一位同事提到了关于emacs的“Keep Lines”以及它有多么有用。甚至不知道我需要这个插件,绝对喜欢它!
brandon927

12

您可以使用Sublime的内置功能在3到7个击键中执行此操作(不包括要匹配的正则表达式)。

第1步:多选所有匹配的行

选项1:多选所有包含子字符串的行

  1. 选择感兴趣的字符串。
  2. 击中 Alt键 + F3 多选所有事件。
  3. 击中 按Ctrl + 大号 (将选择扩展到行)。

选项2:多选选择与正则表达式匹配的所有行

  1. 击中 按Ctrl + F 打开查找抽屉。
  2. 确保启用正则表达式匹配( Alt键 + [R 切换)。
  3. 输入正则表达式。
  4. 击中 Alt键 + 输入 多选所有比赛。
  5. 击中 按Ctrl + 大号 (将选择扩展到行)。

第2步:用这些线做点什么

选项1:摆脱所有线条 不是

  1. 击中 按Ctrl + C 复印。
  2. 击中 按Ctrl + 一个 选择所有。
  3. 击中 按Ctrl + V 用匹配的行替换选择。

选项2:摆脱所有线条

  1. 击中 按Ctrl + 转移 + ķ (删除行)。

选项3:将选定的行提取到新文件

  1. 击中 按Ctrl + C 复印。
  2. 击中 按Ctrl + ñ 打开一个新文件。
  3. 击中 按Ctrl + V 粘贴。

这是一个很好的命令列表!
chustar

超级,但有没有办法去除粘贴后的空白行?
Sergey Senkov

1
@SergeySenkov当然可以! (1)按Ctrl + F打开“查找”抽屉。 (2)确保启用正则表达式匹配(Alt + R切换)。 (3)键入“\ n \ n +”(匹配两个或多个连续的换行符)。 (4)按Alt + Enter可多选所有匹配项。 (5)按Enter键以使用单个换行符替换所有匹配项。
Andres Riofrio
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.