2018年7月26日木曜日

wgrep-ag: Emacsで複数ファイルからの検索結果を対象にして置換する

概要

ディレクトリ以下のファイルを一斉に置換したい。しかも使い慣れたEmacsでと言うときに wgrep-ag.el が便利です。termtosvgで動画を撮ってみました。

サンプルデータ

https://github.com/mamewotoko/emacs_tutorial_data.git
のwgrep_agにあります。0.9を1.0に置換してみます。

手順
  1. M-x ag
  2. 検索対象の文字列を入れる (この場合 0.9)
  3. 対象のディレクトリ名を入れる
  4. C-cC-p (wgrep-change-to-wgrep-mode) で編集可能にする
  5. query-replace で0.9を1.0に置換
  6. C-cC-c (compile-goto-error?) で変更を反映(ファイルには保存されていない)
  7. バッファリストで保存対象のファイルにマーク(m)
  8. Sを押してでマークしたファイルを保存
  9. (magitでdiffをみて結果を確認)
動画
19:57 $  19:57 $ e 19:57 $ em 19:57 $ ema 19:57 $ emac 19:57 $ emacs 19:57 $ emacs  19:57 $ emacs n 19:57 $ emacs                                                          19:57 $ emacs -                                                        19:57 $ emacs -n                                                       19:57 $ emacs -nw                                                       ✔ tak@mamec:~ 19:57 $ emacs -nw                                                                                                                                                                                                                                Loading /Users/tak/dev/ssh-el/ssh.el (source)...                       -UUU:----F1  *scratch*      All L1     (Fundamental) ------------------Loading /Users/tak/dev/ssh-el/ssh.el (source)...done                   Loading /Users/tak/lib/emacs/elisp/myinsert.el (source)...             Loading /Users/tak/lib/emacs/elisp/myjavamode.el (source)...            Loading /Users/tak/lib/emacs/elisp/myinsert.el (source)...done        Loading /Users/tak/lib/emacs/elisp/mymode.el (source)...               Loading /Users/tak/lib/emacs/elisp/mycextend.el (source)...             Loading /Users/tak/lib/emacs/elisp/myerrorjump.el (source)...           Loading /Users/tak/lib/emacs/elisp/mycextend.el (source)...done       Loading /Users/tak/lib/emacs/elisp/mycamlextend.el (source)...         Loading /Users/tak/lib/emacs/elisp/myerrorjump.el (source)...done      Loading /Users/tak/lib/emacs/elisp/mycamlextend.el (source)...done      Loading /Users/tak/lib/emacs/elisp/mymode.el (source)...done      Loading /Users/tak/lib/emacs/elisp/mykeymap.el (source)...             Loading /Users/tak/lib/emacs/elisp/mykeymap.el (source)...done         Loading /Users/tak/lib/emacs/elisp/namazu/namazu.el (source)...        Loading /Users/tak/lib/emacs/elisp/namazu/namazu.el (source)...done    Loading ‘namazu.el’: old-style backquotes detected!                    You appear to be setting environment variables ("PATH" "MANPATH") in y\our .bashrc or .zshrc: those files are only read by interactive shells\, so you should instead set environment variables in startup files lik\e .profile, .bash_profile or .zshenv.  Refer to your shell’s man page\ for more info.  Customize ‘exec-path-from-shell-arguments’ to remov\e "-i" when done, or disable ‘exec-path-from-shell-check-startup-file\ s’ to disable this message.                                            Loading /Users/tak/lib/emacs/elisp/myinit.el (source)...done           Loading help-at-pt...                                                  Loading help-at-pt...done                                              -UUU:----F1  *scratch*      All L1     (Fundamental) 7:57PM 1.80 ------Warning: desktop file appears to be in use by PID 4833.                Using it may cause conflicts.  Use it anyway? (y or n)                 -UUU:----F1  *scratch*      All (1,0)      (Fundamental) 7:57PM 1.80 --Turning on magit-auto-revert-mode...done                               -UUU:----F1  *scratch*      All (1,0)      (Lisp Interaction ElDoc) 7:5For information about GNU Emacs and the GNU system, type <f1> C-a.     Find file in other window: ~/                                          Find file in other window: ~/d                                         Find file in other window: ~/de                                        Find file in other window: ~/dev                                       Find file in other window: ~/dev/                                      Find file in other window: ~/dev/e                                     Find file in other window: ~/dev/em                                    -UUU:----F1  *scratch*      All (4,0)      (Lisp Interaction ElDoc) 7:5Making completion list...                                              In this buffer, type RET to select the completion near point.          Possible completions are:                                              Embedix.tar.gz                     emacs_cheetsheet/                   emacs_docker/                      emacs_tutorial_data/                -UUU:%*--F1  *Completions*   All (1,0)      (Completion List) 7:57PM 1.Find file in other window: ~/dev/ema                                   Find file in other window: ~/dev/emacs_                                emacs_cheetsheet/                                                      emacs_docker/                                                          emacs_tutorial_data/                                                   Find file in other window: ~/dev/emacs_t                               Find file in other window: ~/dev/emacs_tutorial_data/                  Find file in other window: ~/dev/emacs_tutorial_data/wgrep_ag/         Find file in other window: ~/dev/emacs_tutorial_data/wgrep_ag/           -rw-r--r--  1 tak  staff   52  7 26 19:56 README.md                  -UUU:%%--F1  wgrep_ag            All (5,44)     (Dired by name) 7:57PM ls does not support --dired; see ‘dired-use-ls-dired’ for more detai\ls.                                                                    ;; This buffer is for text that is not saved, and for Lisp evaluation. ;; To create a file, visit it with C-x C-f and enter text in its buffe\r.                                                                       -rw-r--r--  1 tak  staff   52  7 26 19:56 README.md                  -UUU:----F1  *scratch*      All (4,0)      (Lisp Interaction ElDoc) 7:5  /Users/tak/dev/emacs_tutorial_data/wgrep_ag:                           total used in directory 56 available 9223372036850188979               drwxr-xr-x  9 tak  staff  288  7 26 19:56 .                            drwxr-xr-x  4 tak  staff  128  7 26 19:53 ..                           -rw-r--r--  1 tak  staff   52  7 26 19:56 README.md                    -rw-r--r--  1 tak  staff   13  7 26 19:53 a.txt                        -rw-r--r--  1 tak  staff   13  7 26 19:53 b.txt                        -rw-r--r--  1 tak  staff   13  7 26 19:53 c.txt                        -rw-r--r--  1 tak  staff   13  7 26 19:53 d.txt                        -rw-r--r--  1 tak  staff   13  7 26 19:53 e.txt                        -rw-r--r--  1 tak  staff   14  7 26 19:53 f.txt                      -UUU:%%--F1  wgrep_ag            All (5,0)      (Dired by name) 7:57PM Starting new Ispell proces       All (5,0)      (Dired by name) 7:57PM replace "0.9" of files in this directory with "1.0"                    -UU-:----F1  README.md      All (1,0)     Git-master  (Markdown Fly AReStarting new Ispell process /usr/local/bin/ispell with default diction\ary...                                                                 M-x                                                                    M-x a                                                                  M-x ag                                                                 M-x ag [Complete, but not unique]                                      replace "0.9" of files in this directory with "1.0"                    M-x ag [Complete, but not unique]                                      Search string (default replace):                                       Search string (default replace):                                       Search string (default replace): 0                                     Search string (default replace): 0.                                    Search string (default replace): 0.9                                   Search string (default replace): 0.9                                   Directory: ~/dev/emacs_tutorial_data/wgrep_ag/                         Directory: ~/dev/emacs_tutorial_data/wgrep_ag/                         -stats -- 0.9 .                                                        -UUU:----F1  *scratch*      All (4,0)      (Lisp Interaction ElDoc) 201-UUU:%%--F1  *ag search*    All (1,0)      (Ag:run [0 0 0] Compiling) 2131 bytes searched                                                     -UUU:%*--F1  *ag search*    All (1,0)      (Ag:run [3 0 0] Compiling) 2Ag finished                                                            End of buffer                                                          -*- mode: ag; default-directory: "~/dev/emacs_tutorial_data/wgrep_ag/"\-UUU:%*--F1  *ag search*    Top (1,0)      (Ag:exit [0] [6 0 0]) 2018/7-UU-:----F1  README.md      All (2,0)     Git-master  (Markdown Fly ARe-*- mode: ag; default-directory: "~/dev/emacs_tutorial_data/wgrep_ag/"\ -*-                                                                   -UUU:%*--F1  *ag search*    Top (1,0)      (Ag:exit [0] [6 0 0]) 2018/7 -*-                                                                   Ag started at Thu Jul 26 19:58:03                                      -UUU:%*--F1  *ag search*    Top (1,70)     (Ag:exit [0] [6 0 0]) 2018/7Ag started at Thu Jul 26 19:58:03                                      -UUU:%*--F1  *ag search*    Top (2,0)      (Ag:exit [0] [6 0 0]) 2018/7ag --nocolor --literal --line-number --smart-case --nogroup --column -\-UUU:%*--F1  *ag search*    Top (3,0)      (Ag:exit [0] [6 0 0]) 2018/7ag --nocolor --literal --line-number --smart-case --nogroup --column -\-stats -- 0.9 .                                                        -UUU:%*--F1  *ag search*    Top (4,0)      (Ag:exit [0] [6 0 0]) 2018/7-stats -- 0.9 .                                                        c.txt:1:10:version: 0.9                                                -UUU:%*--F1  *ag search*    Top (4,70)     (Ag:exit [0] [6 0 0]) 2018/7c.txt:1:10:version: 0.9                                                -UUU:%*--F1  *ag search*    Top (5,0)      (Ag:exit [0] [6 0 0]) 2018/7Press C-x C-s when finished or C-c C-k to abort changes.               Query replace:                                                         Query replace: 0                                                       Query replace: 0.                                                      Query replace: 0.9                                                     Query replace: 0.9                                                     Query replace 0.9 with:                                                Query replace 0.9 with: 1                                              Query replace 0.9 with: 1.                                             Query replace 0.9 with: 1.1                                            Query replace 0.9 with: 1.0                                            Query replace 0.9 with: 1.0                                            -UUU:----F1  *ag search*    Top (5,0)      (Ag:exit [0] [12 0 0]) 2018/c.txt:1:10:version: 0.9                                                -UUU:----F1  *ag search*    Top (5,23)     (Ag:exit [0] [12 0 0]) 2018/Mark set                                                               c.txt:1:10:version: 0.9                                                b.txt:1:10:version: 0.9                                                README.md:1:10:replace "0.9" of files in this directory with "1.0"     e.txt:1:10:version: 0.9                                                d.txt:1:10:version: 0.9                                                a.txt:1:10:version: 0.9                                                Query replacing 0.9 with 1.0: (? for help)                             a.txt:1:10:version: 1.0                                                Replaced 6 occurrences                                                 c.txt:1:10:version: 1.0                                                b.txt:1:10:version: 1.0                                                README.md:1:10:replace "1.0" of files in this directory with "1.0"     e.txt:1:10:version: 1.0                                                d.txt:1:10:version: 1.0                                                -UUU:**--F1  *ag search*    Top (10,23)    (Ag:exit [0] [18 0 0]) 2018/a.txt:1:10:version: 1.0                                                -UUU:%%--F1  *ag search*    Top (10,23)    (Ag:exit [0] [18 0 0]) 2018/-UU-:----F1  README.md      All (2,0)     Git-master  (Markdown Fly ARea.txt:1:10:version: 1.0                                                Successfully finished. (6 changed)                                     Updating buffer list...                                                Formats have changed, recompiling...                                   Formats have changed, recompiling...done                               c.txt:1:10:version: 1.0                                                b.txt:1:10:version: 1.0                                                README.md:1:10:replace "1.0" of files in this directory with "1.0"     e.txt:1:10:version: 1.0                                                d.txt:1:10:version: 1.0                                                Commands: m, u, t, RET, g, k, S, D, Q; q to quit; h for help             %  *ag search*              508 Ag                                    *   e.txt                     13 Text             ~/dev/emacs_tuto    6 matches                                                              6 files contained matches                                              7 files searched                                                       131 bytes searched                                                     0.004387 seconds                                                       -UUU:%%--F1  *ag search*    Top (10,0)     (Ag:exit [0] [18 0 0]) 2018/replace "1.0" of files in this directory with "1.0"                    -UU-:**--F1  README.md      All (2,0)     Git-master  (Markdown Fly ARe  %  *ag search*              508 Ag                                    *   README.md                 52 Markdown         ~/dev/emacs_tutoria$-UUU:%%--F1  *Ibuffer*      All (4,0)      (IBuffer by recency) 2018/7/   README.md                 52 Markdown         ~/dev/emacs_tutoria$  %  wgrep_ag                 553 Dired by name    ~/dev/emacs_tutoria$-UUU:%%--F1  *Ibuffer*      All (5,0)      (IBuffer by recency) 2018/7/  %  wgrep_ag                 553 Dired by name    ~/dev/emacs_tutoria$     *scratch*                145 Lisp Interaction                     -UUU:%%--F1  *Ibuffer*      All (6,0)      (IBuffer by recency) 2018/7/     *scratch*                145 Lisp Interaction                      *%  *Messages*              2180 Messages                             -UUU:%%--F1  *Ibuffer*      All (7,0)      (IBuffer by recency) 2018/7/ *%  *Messages*              2180 Messages                              *%  *Completions*            141 Completion List                      -UUU:%%--F1  *Ibuffer*      All (8,0)      (IBuffer by recency) 2018/7/ *%  *Completions*            141 Completion List                       *   d.txt                     13 Text             ~/dev/emacs_tutoria$-UUU:%%--F1  *Ibuffer*      All (9,0)      (IBuffer by recency) 2018/7/   d.txt                     13 Text             ~/dev/emacs_tutoria$ *   e.txt                     13 Text             ~/dev/emacs_tutoria$-UUU:%%--F1  *Ibuffer*      All (10,0)     (IBuffer by recency) 2018/7/   e.txt                     13 Text             ~/dev/emacs_tutoria$ *   b.txt                     13 Text             ~/dev/emacs_tutoria$-UUU:%*--F1  *Ibuffer*      All (11,0)     (IBuffer by recency) 2018/7/   b.txt                     13 Text             ~/dev/emacs_tutoria$ *   c.txt                     13 Text             ~/dev/emacs_tutoria$-UUU:%*--F1  *Ibuffer*      All (12,0)     (IBuffer by recency) 2018/7/   c.txt                     13 Text             ~/dev/emacs_tutoria$ *   a.txt                     13 Text             ~/dev/emacs_tutoria$-UUU:%*--F1  *Ibuffer*      All (13,0)     (IBuffer by recency) 2018/7/   a.txt                     13 Text             ~/dev/emacs_tutoria$-UUU:%*--F1  *Ibuffer*      All (14,0)     (IBuffer by recency) 2018/7/Saving file /Users/tak/dev/emacs_tutorial_data/wgrep_ag/d.txt...       Wrote /Users/tak/dev/emacs_tutorial_data/wgrep_ag/d.txt                Saving file /Users/tak/dev/emacs_tutorial_data/wgrep_ag/e.txt...       Wrote /Users/tak/dev/emacs_tutorial_data/wgrep_ag/e.txt                Saving file /Users/tak/dev/emacs_tutorial_data/wgrep_ag/b.txt...       Wrote /Users/tak/dev/emacs_tutorial_data/wgrep_ag/b.txt                Saving file /Users/tak/dev/emacs_tutorial_data/wgrep_ag/c.txt...       Wrote /Users/tak/dev/emacs_tutorial_data/wgrep_ag/c.txt                Saving file /Users/tak/dev/emacs_tutorial_data/wgrep_ag/a.txt...       Wrote /Users/tak/dev/emacs_tutorial_data/wgrep_ag/a.txt                >*   d.txt                     13 Text             ~/dev/emacs_tutoria$>*   e.txt                     13 Text             ~/dev/emacs_tutoria$>*   b.txt                     13 Text             ~/dev/emacs_tutoria$>*   c.txt                     13 Text             ~/dev/emacs_tutoria$>*   a.txt                     13 Text             ~/dev/emacs_tutoria$     11 buffers              3644                  7 files, no process$-UUU:%*--F1  *Ibuffer*      All (4,0)      (IBuffer by recency) 2018/7/Operation finished; saved 5 buffers                                    C-x-                                                                   C-x o                                                                   MRL Name                    Size Mode             Filename/Process     --- ----                    ---- ----             ----------------    [ Default ]                                                             *%  *Messages*              2874 Messages                             >    d.txt                     13 Text             ~/dev/emacs_tutoria$>    e.txt                     13 Text             ~/dev/emacs_tutoria$>    b.txt                     13 Text             ~/dev/emacs_tutoria$>    c.txt                     13 Text             ~/dev/emacs_tutoria$>    a.txt                     13 Text             ~/dev/emacs_tutoria$     11 buffers              4338                  7 files, no process$-UUU:%%--F1  *Ibuffer*      All (4,0)      (IBuffer by recency) 2018/7/-UU-:**--F1  README.md      All (2,0)     Git-master  (Markdown Fly AReSave file /Users/tak/dev/emacs_tutorial_data/wgrep_ag/README.md? (y, n\, !, ., q, C-r, d or <nil>)                                            Save file /Users/tak/dev/emacs_tutorial_data/wgrep_ag/README.md? (y, n\, !, ., q, C-r, d or <nil>) y                                          Head:     master add file to replace                                   -UUU:%%--F1  *magit: emacs_tutorial_data   All (1,0)      (Magit) 2018/Head:     master add file to replace                                   Unstaged changes (6)                                                   modified   wgrep_ag/README.md                                          modified   wgrep_ag/a.txt                                              modified   wgrep_ag/b.txt                                              modified   wgrep_ag/c.txt                                              modified   wgrep_ag/d.txt                                              modified   wgrep_ag/e.txt                                              -UUU:%%--F1  *magit: emacs_tutorial_data   All (2,0)      (Magit) 2018/Unstaged changes (6)                                                   -UUU:%%--F1  *magit: emacs_tutorial_data   All (3,0)      (Magit) 2018/modified   wgrep_ag/README.md                                          -UUU:%%--F1  *magit: emacs_tutorial_data   All (4,0)      (Magit) 2018/Switches                                                                =a Diff algorithm (-                                                  Switches                                                                =m Detect renames (-M)                                                [C-t] show common commands, [?] describe events, [C-h i] show manual   -UUU:%%--F1  *magit: emacs_tutorial_data   Top (3,0)      (Magit) 2018/ -f Show surrounding functions (--function-context)                     -b Ignore whitespace changes (--ignore-space-change)                   -w Ignore all whitespace (--ignore-all-space)                          -x Disallow external diff drivers (--no-ext-diff)                      -s Show stats (--stat)                                                Options                                                                 =f Limit to files (-- )                                                =u Context lines (-U)                                                  =m Detect renames (-M)                                                 =c Detect copies (-C)                                                  =c Detect copies (-C)                                                  =a Diff algorithm (--diff-algorithm=)                                 Actions                                                                 d Dwim             u Diff unstaged    c Show commit                    r Diff range       s Diff staged      t Show stash                     p Diff paths       w Diff worktree                                     p Diff paths       w Diff worktree                                    -UUU:%%--F1  *magit-diff-popup*   All (1,0)      (MagitPopup) 2018/7/26-UU-:----F1  README.md      All (2,0)     Git:master  (Markdown Fly ARe6 files changed, 6 insertions(+), 6 deletions(-)                       -UUU:%%--F1  *magit-diff: emacs_t2,0)     Git:master  (Markdown Fly ARe6 files changed, 6 insertions(+), 6 deletions(-)                       wgrep_ag/a.txt     | 2 +-                                              wgrep_ag/b.txt     | 2 +-                                              wgrep_ag/c.txt     | 2 +-                                              wgrep_ag/d.txt     | 2 +-                                              wgrep_ag/e.txt     | 2 +-                                              wgrep_ag/README.md | 2 +-                                              -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (1,0)      (Magit Dwgrep_ag/README.md | 2 +-                                              -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (2,0)      (Magit Dwgrep_ag/a.txt     | 2 +-                                              -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (3,0)      (Magit Dwgrep_ag/b.txt     | 2 +-                                              -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (4,0)      (Magit Dwgrep_ag/c.txt     | 2 +-                                              -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (5,0)      (Magit Dwgrep_ag/d.txt     | 2 +-                                              -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (6,0)      (Magit Dwgrep_ag/e.txt     | 2 +-                                              -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (7,0)      (Magit D@@ -1 +1 @@                                                            -replace "0.9" of files in this directory with "1.0"                   +replace "1.0" of files in this directory with "1.0"                   +replace "1.0" of files in this directory with "1.0"                   -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (8,0)      (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (9,0)      (Magit D@@ -1 +1 @@                                                            -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (10,0)     (Magit D-replace "0.9" of files in this directory with "1.0"                   -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (11,0)     (Magit D-version: 0.9                                                          +version: 1.0                                                          -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (12,0)     (Magit Dmodified   wgrep_ag/a.txt                                              -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (13,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (14,0)     (Magit D-version: 0.9                                                          -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (15,0)     (Magit D+version: 1.0                                                          -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (16,0)     (Magit Dmodified   wgrep_ag/b.txt                                              -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Top (17,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data    8% (18,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   11% (19,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   15% (20,0)     (Magit Dmodified   wgrep_ag/c.txt                                              -UUU:%%--F1  *magit-diff: emacs_tutorial_data   19% (21,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   23% (22,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   27% (23,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   30% (24,0)     (Magit Dmodified   wgrep_ag/d.txt                                              -UUU:%%--F1  *magit-diff: emacs_tutorial_data   31% (25,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   35% (26,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   37% (27,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   44% (28,0)     (Magit Dmodified   wgrep_ag/e.txt                                              -UUU:%%--F1  *magit-diff: emacs_tutorial_data   52% (29,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   56% (30,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   58% (31,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   60% (32,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   Bot (33,0)     (Magit D-UUU:%%--F1  *magit-diff: emacs_tutorial_data   Bot (34,0)     (Magit D-UUU:%%--F1  *magit: emacs_tutorial_data   All (3,0)      (Magit) 2018/-UUU:%%--F1  *magit-diff: emacs_tutorial_data   Bot (32,0)     (Magit DSave desktop? (y or n)                                                  Unstaged changes                                                      -UUU:%%--F1  *magit-diff: emacs_tutorial_data   Bot (32,0)     (Magit D✔ tak@mamec:~                                                          19:58 $  19:58 $ exit
別の方法

sedでいうと以下のような感じ

sed -i '' -e 's/0\.9/1.0/g' *

0 件のコメント:

コメントを投稿