web-dev-qa-db-ja.com

Emacsを使用して、まだ開いていないテキストファイルを再帰的に検索して置換する

この質問 のフォローアップとして、このような簡単な方法を見つけようとしています。特に、Emacsを使用することに慣れるのを止め、代わりにエディターを起動します。すでに知っています。ここでは、複数のファイルの編集にかなり頻繁に例を使用しています。

Ultraeditでは、Alt + sを押してからpを押して、次のオプションのダイアログボックスを表示します。検索(複数行にわたる正規表現の使用を含む)、置換、ファイル/タイプ、ディレクトリ、大文字と小文字の区別、単語のみの一致、リスト変更されたファイルとサブディレクトリの検索。通常、最初にマウスを使用して、置換するテキストをクリックしてドラッグします。

外部ユーティリティを呼び出さずにEmacsのみを使用して(Windows XPで)、一部のフォルダーとその下のすべてのフォルダーの*.cおよび*.hファイルのすべてのfoo\nbarをbar\nbazに置き換える方法Emacsはこれを行うのに最適なツールではないかもしれませんが、最小限のコマンドでどのように簡単に実行できますか?

204
Rob Kam
  1. M-x find-name-dired:ルートディレクトリとファイル名パターンの入力を求められます。
  2. tを押して、見つかったすべてのファイルの「マークを切り替え」ます。
  3. 「Query-Replace in Files ...」のQを押します。クエリ/置換正規表現の入力を求められます。
  4. query-replace-regexpの場合と同様に続行します:SPACEは置換して次の一致に移動し、nは一致をスキップします。
  5. C-x sを押してバッファーを保存します。 (yn、または!を押すと、すべてを一度に保存できます)
351
Chris Conway
  • M-x find-name-dired RET
    • すべてのファイルがリストに表示されるまで時間がかかる場合があります。最後までスクロールしてください(M->)「find finished "がすべて読み込まれたことを確認するように見えます
  • tを押して、見つかったすべてのファイルの「マークを切り替え」ます
  • 「Query-Replace in Files ...」のQを押します。クエリ/置換正規表現の入力を求められます。
  • Query-replace-regexpの場合と同様に進みます:SPACEまたはyは置換して次の一致に移動し、nは一致をスキップします。
    • タイプ!確認せずに現在のファイル内のすべてのオカレンスを置き換えるには、Nを使用して、現在のファイルの残りのすべての可能な置換をスキップします。 (Nはemacs 23+のみ)
    • 確認せずにすべてのファイルで置換を行うには、Yと入力します。
  • 「ibuffer」を呼び出す(C-x C-b ibufferにバインドされている場合、またはM-x ibuffer RET)開いているすべてのファイルをリストします。
  • タイプ* u未保存のすべてのファイルをマークするには、Sと入力して、マークされたすべてのファイルを保存します
  • * * RETすべてのマークのマークを解除するか、Dと入力してすべてのマークされたファイルを閉じます

この回答は this answerthis site 、および私自身のメモから組み合わされています。 Emacs 23+を使用します。

36
Frank Henard

私は通常、このタスクを実行するために他のツールを使用し、 EmacsWikiのファイル間検索および置換エントリ シェルアウトで言及されているアプローチの多くのように見えますが、 Findrパッケージ は非常に見えます有望。

ソースファイル の一部を盗む

(defun findr-query-replace (from to name dir)
  "Do `query-replace-regexp' of FROM with TO, on each file found by findr.
13
Blair Conrad

提供された答えは素晴らしいですが、少し異なるアプローチを追加すると思いました。

これはよりインタラクティブな方法であり、wgreprgrep、およびieditが必要です。 ieditwgrepの両方をMELPAまたはMarmalade経由でインストールする必要があります(M-x package-list-packagesを使用)

最初にM-x rgrepを実行して、探している文字列を見つけます。

ファイルの種類/パターンと再帰するフォルダーを指定できます。

次に、wgrepを実行し、C-s C-pで開始する必要があります。

Wgrepではrgrepの結果を編集できるため、文字列に一致する領域を設定し、iedit-modeC-;で開始します(端末によっては、これを再バインドする必要があります)

すべての出現は一度に編集可能です。 C-x C-sコミットするwgrep。次に、C-x s !をクリックして、変更されたファイルを保存します。

この方法の主な利点は、iedit-modeを使用して特定の一致M-;をオフにできることです。予期しない一致がある場合など、rgrepの結果を使用してファイルにジャンプすることもできます。

プロジェクト全体でソース編集を行い、シンボル(変数、関数名など)の名前を変更するのに非常に便利です。

Ieditモードをまだ知らない/使用していない場合は、非常に便利なツールです。ぜひご覧ください。

12
ocodo

発射物は本当に素晴らしいです:C-c p rはコマンドの発射物交換を実行します

9
eflanigan00

Diredを使用して深いディレクトリツリーを再帰処理することは、このタスクでは少し遅くなります。 tags-query-replace の使用を検討してください。これは、タグテーブルを作成するために砲撃することを意味しますが、とにかく多くの場合に便利であり、迅速です。

5
Alex Coventry

情報源: 1

emacs proユーザーの場合:

  1. Diredを呼び出してdir内のファイルを一覧表示するか、すべてのサブディレクトリが必要な場合はfind-diredを呼び出します。
  2. 必要なファイルをマークします。 「%m」と入力すると、正規表現でマークできます。
  3. Qと入力して、dired-do-query-replace-regexpを呼び出します。
  4. 検索正規表現を入力し、文字列を置き換えます。 〔☛一般的なelisp正規表現パターン〕
  5. 出現するたびに、yを入力して置き換え、nを入力してスキップします。操作全体を中止するには、[Ctrl + g]を入力します。
  6. タイプ!確認せずに現在のファイル内のすべてのオカレンスを置換するには、Nは現在のファイルの残りのすべての可能な置換をスキップします。 (Nはemacs 23のみ)
  7. さらに尋ねることなくすべてのファイルで置換を行うには、Yと入力します(Emacs 23のみ)。
  8. Ibufferを呼び出して、開いているすべてのファイルをリストします。 「* u」と入力して未保存のファイルをすべてマークし、Sと入力してすべてのマークされたファイルを保存し、Dと入力してそれらをすべて閉じます。

Emacs初心者向けのステップバイステップガイド

ターゲットファイルを選択

コマンドラインインターフェイスプロンプトで「emacs」と入力して、emacsを起動します。 (または、グラフィックユーザーインターフェイス環境にいる場合は、Emacsアイコンをダブルクリックします)

ディレクトリ内のファイルを選択する

最初に、置換を行うファイルを選択する必要があります。グラフィカルメニューの「ファイル」▸「ディレクトリを開く」を使用します。 Emacsはディレクトリパスを尋ねてきます。ディレクトリパスを入力し、Enterキーを押します。

これで、ファイルのリストが表示されます。次に、正規表現の検索/置換で作業するファイルをマークする必要があります。目的のファイルにカーソルを移動してファイルをマークし、mを押します。 uを押してマークを解除します。 (サブディレクトリを一覧表示するには、ディレクトリにカーソルを移動してiを押します。サブディレクトリのコンテンツが下部に一覧表示されます。)正規表現ですべてのファイルをマークするには、「%m」と入力し、正規表現パターンを入力します。たとえば、すべてのHTMLファイルをマークする場合は、【%m】を入力してから.html $を入力します。 (マークコマンドのリストは、グラフィカルメニューの[マーク]にあります(このメニューは、diredモードのときに表示されます)。)

ディレクトリとそのすべてのサブディレクトリ内のファイルの選択

数百のサブディレクトリを含むディレクトリ内のファイルを検索/置換したい場合、これらすべてのファイルを選択する方法があります。

Find-diredを呼び出します。 ([Alt + x]を押してコマンドを呼び出します)次に、ディレクトリ名を入力します、⁖/ Users/mary/myfiles

注:UNIXの非グラフィカルテキスト端末でemacsを使用しており、【Alt + x】が機能しない場合、同等のキーストロークは【Esc x】です。

Emacsは「Run find(with args):」というプロンプトで尋ねます。すべてのHTMLファイルで置換を行う必要がある場合は、-name "* html"と入力します。どんな種類のファイルを気にせず、単にそのディレクトリの下にあるすべてのファイルを気にする場合は、「-type f」を指定します。

次に、上記のようにファイルをマークします。

インタラクティブな検索/置換

これで、インタラクティブな検索置換を実行する準備が整いました。簡単にするために、Wordの「quick」を「super」に置き換えたいとしましょう。次に、dired-do-query-replace-regexpを呼び出します。正規表現文字列と置換文字列の入力を求められます。 「quick」と入力し、入力してから「super」と入力します。

これで、emacsはパターンを使用してファイルをチェックし、一致するたびに停止して表示します。これが発生すると、emacsがプロンプトを表示し、変更を行うか、変更をスキップするかを選択できます。変更するには、yと入力します。スキップするには、nと入力します。 emacsで現在のファイルにこのような変更をすべて加えたい場合は、!と入力します。

行った変更を保存せずに操作全体をキャンセルする場合は、【Ctrl + g】を入力し、メニュー〖[ファイル]▸[Emacsの終了]を使用してemacsを終了します。

変更したファイルを保存する

さて、あなたが上記の試練を経た後、あなたがする必要があるもう一つのステップがあり、それは変更されたファイルを保存しています。

Emacsバージョン22以降を使用している場合は、ibufferを呼び出してバッファーリストモードに入り、[* u]を入力してすべての未保存ファイルをマークし、Sを入力してすべて保存します。 (それはshift-sです)

Emacsバージョン21を使用している場合、これを行うことができます。リストバッファーを呼び出し、保存するファイルにカーソルを移動してsと入力します。後で保存するためにファイルをマークします。 uを入力してマークを解除します。完了したら、xと入力して、保存のマークが付いているすべてのファイルの保存を実行します。 (emacsでは、開かれたファイルは「バッファ」と呼ばれます。他のファイルは無視してください。)

上記のオプションの代わりに、save-some-buffers【Ctrl + x s】を呼び出すこともできます。その後、emacsは未保存の各ファイルを表示し、保存するかどうかを尋ねます。

注:emacsの正規表現はPerlやPythonの正規表現とは異なりますが、類似しています。要約と一般的なパターンについては、Emacs Regexを参照してください。

4
scrapcodes

M-X Dired、およびtはすべてのファイルをマークし、Qはクエリを実行してすべてのファイルのテキストを置き換えます。 query-replaceの前にiコマンドを使用して、サブディレクトリを展開できます。私が追加している重要な情報は、iコマンドにプレフィックス(control-u)を与えると、argのプロンプトが表示され、-R引数がすべてのsubdirsdiredバッファ。そのため、ディレクトリ全体のすべてのファイルをクエリ検索できます。

3
Zack Murray

オープンバッファの場合、これは私が行うことです:

(defun px-query-replace-in-open-buffers (arg1 arg2)
  "query-replace in all open files"
  (interactive "sRegexp:\nsReplace with:")
  (mapcar
   (lambda (x)
     (find-file x)
     (save-excursion
       (goto-char (point-min))
       (query-replace-regexp arg1 arg2)))
   (delq
    nil
    (mapcar
     (lambda (x)
       (buffer-file-name x))
     (buffer-list)))))
3
yPhil

別のオプションは Icicles search を使用することです。これは、検索ヒットに対してミニバッファー入力の完了を使用する、異なる種類のインクリメンタル検索です。現在の入力を変更すると、一致するヒットのセットがバッファ*Completions*で更新されます。

任意の数のファイル、バッファ、またはブックマークされた場所を検索できます。ミニバッファパターン(regexpなど)マッチングを使用して選択できます。

検索ヒットにアクセスすると、 replace ヒット全体、または現在のミニバッファ入力に一致するヒットの一部のみがオンデマンドでできます。オンデマンド置換は、各検索ヒットについて順番に照会されないことを意味します。任意の順序で、必要なヒットに直接アクセスします。このアプローチは、置換の数が限られている場合、query-replaceよりも効果的です。徹底的なy/nプロンプトをスキップします。

検索はオーバーサーチですcontextsあなたが定義する-ターゲットファイル内のすべてのテキストの検索に限定されません(例えば、コメントや特定の種類のプログラムセクションをスキップできます)。検索コンテキストの簡単な例は、grepのような行ですが、コンテキストは、パターンに一致する任意のテキストブロックにすることができます。通常、正規表現を使用して検索コンテキストを定義しますが、代わりに関数を使用できます。独自の定義に加えて、さまざまな種類のコンテキスト用の事前定義されたIcicles検索コマンドがあります:テキストプロパティまたはオーバーレイプロパティのブロック、ポイントアットシングなど。

sort検索ヒットをさまざまなソート順でヒットして、アクセス/ナビゲーションを容易にすることもできます。

1
Drew

まだ言及されていないもう1つの素晴らしいツール、つまりHelmを提案したいと思います。

補完、検索などを含む多くの標準的なEmacs操作の優れた代替品です。特に、helm-find-filesは、選択した複数のファイル内でクエリ置換(正規表現を含む)を実行できます。

helm-find-filesを開き、関連ファイルをM-SPCでマークし、F6またはF7を使用して、選択したファイルでクエリ置換またはクエリ置換正規表現を実行します。

1

_find-name-dired_は問題ありませんが、次のとおりです。

  • 取得するすべてのファイルは、同じ単一の正規表現に一致します。
  • _find-dired_はその点でより柔軟性がありますが、一般的なルールを使用するために作られています(たとえ任意に複雑な場合でも)。そしてもちろんfindには独自の複雑な言語があります。
  • 名前がfind(-name)-diredバッファーに収集されたファイルの一部のみを処理する場合は、それらをマークするか、処理しないファイルの行を削除/除外する必要があります。

別の方法は、 Dired + に作用するコマンドを使用することです(a) マークされたサブディレクトリ内のマークされたファイルと(b)すべてのマークされたファイル(またはマークされていない場合はすべてのファイル)... foundrecursively。これにより、ファイル選択の一般性と簡単な制御の両方が得られます。これらの「here-and-below」コマンドはすべて、Diredモードのプレフィックスキー_M-+_にあります。

たとえば、_M-+ Q_Q --- query-replaceと同じですが、ターゲットファイルはすべて現在のディレクトリおよびマークされたサブディレクトリでマークされたもの、ダウン、ダウン、ダウン...

はい、このような以下のコマンドを使用する代わりに、すべてのサブディレクトリとそのサブディレクトリを再帰的にinsertしてから、Q。しかし、多くの場合、挿入されたサブディレクトリに煩わされない方が便利です。

とにかくそれを行うには、とにかくすべてのサブディレクトリを再帰的に挿入する簡単な方法が必要です。ここでも、Dired +が役立ちます。 _M-+ M-i_は、マークされたすべてのサブディレクトリとマークされたサブディレクトリを再帰的に挿入します。つまり、_M-i_(マークされたサブディレクトリをDired +に挿入します)に似ていますが、サブディレクトリに対して再帰的に動作します。

(このような「here-and-below」Dired +コマンドはすべてメニューにありますMultiple>ここと下にマーク。)

EmacsfilesetでDired操作を実行することもできます。これは、任意の場所にあるファイルの名前の保存セットです。 Icicles を使用すると、Diredバッファーを開くことができますファイルセット内のファイルまたは他の種類の保存済みファイルリストのみ。

また、find(-name)-diredを使用して作成したものを含め、Diredバッファーをbookmarkすることもできます。これにより、後でそのようなセット(プロジェクトセットなど)にすばやく戻ることができます。 Bookmark + を使用すると、Diredバッファーレコードをブックマークする(a )lsスイッチ、(b)マークされているファイル、(c)挿入されているサブディレクトリ、(d)隠されている(サブ)ディレクトリこれらはすべて、ブックマークに「ジャンプ」すると復元されます。 Bookmark +は、Diredバッファーのツリー全体をブックマークすることもできます---ブックマークにジャンプすると、ツリー内のすべてのバッファーが復元されます。

1
Drew