

Emacsで“ある文字A”と“ある文字B”に挟まれた“ある文字C”を、確認つき（query）で削除するコマンドを教えてください。

具体例として、「2つの“x”に挟まれた空白1つだけを削除する」ことにします。これを実行するコマンドを教えてください。

ここで、バッファが以下の内容となっているとします。

[code]

    x x x x y
    
[/code]

望む結果は以下のとおりです。

[code]

    xxxx y
    
[/code]

たとえば`M-% x x RET xx RET`を実行した場合は、`!`で全部置換しても当然以下のようになり、要件を満たしません。

[code]

    xx xx y
    
[/code]

置換を2回実行するか、replace-search-
functionを再定義するぐらいしか思いつかないのですが、よくあるシチュエーションで解がすでにあるのではないかと思ってお聞きします。


CC BY-SA 3.0
2014-12-16T14:31:29.037
1788
2015-01-06T14:38:12.150
4010
question
emacs
Emacsでxとxに挟まれた空白を確認つきで削除したい


Emacs の正規表現には lookahead がないので `M-x query-replace-regexp` では無理っぽいですね。

私は必要なら、深く考えずに Elisp 書きます:

[code]

    (while (search-forward "x x")
      (if (y-or-n-p "replace?") (replace-match "xx"))
      (backward-char 1)) ;; 最後の x に戻って検索しなおす
    
[/code]

[文字列中のアイテムを置換したくない場合の定石は?](https://ja.stackoverflow.com/questions/1709/) に
Perl を呼び出して lookahead を使う方法があるようですが、これだと query なしで一気に書き換えることになります。


CC BY-SA 3.0
2014-12-16T15:55:35.313
1799
2014-12-16T16:00:38.060
2014-12-16T16:00:38.060
898
898
1788
answer

[code]

    (defun whatever-you-want ()
      "Put proper explanation here"
      (interactive nil)
      (while (search-forward "x x")
        (if (y-or-n-p "replace?")
          (replace-match "xx"))
        (backward-char 1)))
    
[/code]

とちゃんと関数として定義して実行してみましたが、期待された動きをすると思います (camlspotterさんの投稿へのコメントにしたかったのですが、まだ
reputation が足りなかったので独立した回答で)。


CC BY-SA 3.0
2014-12-16T21:48:15.977
1819
2014-12-16T21:48:15.977
2521
1788
answer


`query-replace-regexp` のドキュメントによると

[code]

    In interactive calls, the replacement text can contain `\,'
    followed by a Lisp expression.  Each
    replacement evaluates that expression to compute the replacement
    string.  Inside of that expression, `\&' is a string denoting the
    whole match as a string, `\N' for a partial match, `\#&' and `\#N'
    for the whole or a partial match converted to a number with
    `string-to-number', and `\#' itself for the number of replacements
    done so far (starting with zero).
    
[/code]

Lisp 式が書けるので、

[code]

    \(x \)+x
    
[/code]

を

[code]

    \,(replace-regexp-in-string " " "" \&)
    
[/code]

もしくは

[code]

    \,(make-string (1+ (/ (length \&) 2)) ?x)
    
[/code]

に置換することでできます。


CC BY-SA 3.0
2015-01-06T14:06:45.000
3208
2015-01-06T14:38:12.150
2015-01-06T14:38:12.150
6148
6148
1788
answer