web-dev-qa-db-ja.com

Sublime Text 2で文字列を含む行のファイルをフィルタ処理する方法を教えてください。

Sublime Text 2で編集中のファイルを、可能であれば正規表現を含めて特定の文字列が含まれている行に絞り込みます。

次のファイルを検討してください。

foo bar
baz
qux
quuux baz

baに対してフィルタ処理されると、結果は以下のようになります。

foo bar
baz
quuux baz

どうやってやるの?

73
Daniel Beck

Sublime Text 2は Python API を持つ拡張可能なエディタです。新しいコマンド(Pluginsと呼ばれる)を作成して、それらを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との統合

このプラグインをEditメニューに追加するには、Preferences…"Browse Packagesを選択してUserフォルダを開きます。 Main.sublime-menuというファイルが存在しない場合は作成します。そのファイルに次のテキストを追加または設定します。

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

これはfilterコマンド呼び出しのすぐ下にfilterコマンド呼び出しを挿入します(基本的に、プラグイン呼び出しの場合はwrapFilterCommand().run(…)に、メニューラベルの場合はFilterに変換されます)。その理由については、 ここのステップ11 を参照してください。

キーボードショートカットを割り当てるには、OS Xの場合はファイルDefault (OSX).sublime-keymap、または他のシステムの場合は同等のファイルを開いて編集し、次のように入力します。

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

これはショートカットを割り当てます F このコマンドに。


コマンドをCommands Paletteに表示するには、UserフォルダーにDefault.sublime-commandsという名前のファイルを作成する(または既存のファイルを編集する)必要があります。構文は、先ほど編集したメニューファイルと似ています。

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

複数のエントリ(中括弧で囲まれている)は、カンマで区切る必要があります。

動作とUI統合のスクリーンショット

このコマンドは、実装されているとおり、入力フィールドに入力された部分文字列について、選択範囲の一部であるすべての行(選択された部分だけでなく、行全体)、またはバッファ全体をフィルタリングします。コマンドが起動された後のデフォルトは - おそらく無駄な複数行 - クリップボード)です。それは容易に拡張することができます。正規表現をサポートするか、またはnotが特定の表現に一致する行だけを残します。

メニュー項目

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

2番目のプラグインコマンド、正規表現を使用したフィルタは、Filterメニューエントリの下に追加されます。

Default.sublime-commands

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

貧乏人のラインフィルタリングアルゴリズムもあります(またはそれは怠け者ですか?)

  1. 選択興味のある文字列
  2. ヒット Alt+F3 すべてのオカレンスでマルチカーソルモードに入る
  3. ヒット Control+L 行全体を選択する(すべてのカーソル行)
  4. 選択を別のバッファにコピー&ペーストする
82
Olof Bjarnason

行をフィルタリングするためのプラグインがあります。 https://github.com/davidpeckham/FilterLines
文字列や正規表現に基づいたフィルタリングやコードの折りたたみが可能です。


Sublime Text Filter Plugin by David Peckham

48
AllanLRH

Sublimeの組み込み機能を使用して、これを3〜7回のキーストロークで一致させることができます(照合対象の正規表現は含まれません)。

ステップ1:一致するすべての行を複数選択

オプション1:部分文字列を含むすべての行を複数選択する

  1. 興味のある文字列を選択します。
  2. ヒット Alt+F3 すべての発生を複数選択する。
  3. ヒット Ctrl+L (選択範囲を行に展開).

オプション2:正規表現に一致するすべての行を複数選択する

  1. ヒット Ctrl+F 検索ドロワーを開く。
  2. 正規表現のマッチングが有効になっていることを確認してください(Alt+R トグルへ)。
  3. 正規表現を入力してください。
  4. ヒット Alt+Enter すべての一致を複数選択します。
  5. ヒット Ctrl+L (選択範囲を行に展開).

ステップ2:それらの行で何かをする

オプション1:が選択されていないすべての行を削除する

  1. ヒット Ctrl+C コピーする。
  2. ヒット Ctrl+A すべて選択します。
  3. ヒット Ctrl+V 選択範囲を一致する行に置き換えます。

オプション2:選択されているすべての行を削除する

  1. ヒット Ctrl+Shift+K (行削除).

オプション3:選択した行を新しいファイルに抽出する

  1. ヒット Ctrl+C コピーする。
  2. ヒット Ctrl+N 新しいファイルを開きます。
  3. ヒット Ctrl+V 貼り付けます。
14
Andres Riofrio