0

Vimでこの検索を行い、次のものを置き換える良い方法を見つけたいと思います-

name_1
end
name_2
end

name_3
end

ここで、name_"x" を取り、次の "end" ステートメントに追加します。したがって、次のようになります-

name_1
end_name_1
name_2
end_name_2
name_3

end_name_3

注 - name_3 の前の空行は、"name_x" と "end" の間の一定の行間隔を台無しにします。だから私は次のようなことを考えていました

:g/\(name_x\)/,/end/ s/end/end_\1/

そのような最初のパターンを保存しようとしてもうまくいきませんが、うまくいけばアイデアが得られます。ここにトリックはありますか?

ありがとう

4

1 に答える 1

3

あなたが抱えている問題は、コマンドのパターン\1ではなく、現在の置換の一致グループを参照することです。:g残念ながら、以前の検索から以前の一致グループにアクセスすることはできません。ただし、目標を達成する方法はあります。最初にお勧めしたいのはマクロです。

まず、一致しない行から始めます。これは、必要に応じてファイルの先頭に空白行を挿入することで実行できます (後で削除するだけです)。

  1. パターンのマクロ検索を開始します。/name_\d\+
  2. パターンの最後までヤンクします。y//e
  3. 終了パターンを見つける:/end/e
  4. アンダースコアを挿入するa_
  5. で貼り付けるp
  6. マクロを終了しますq
  7. 大きな数でマクロを実行します。例えば999@q

使用したマクロは次のとおりです。

:let @q = "/name_\\d\\+\<cr>y//e\<cr>/end/e\<cr>a_\<esc>p"

もう 1 つの方法は:global、試行と同様の方法でコマンドを使用することです。

:g/name_\d\+/let @@=matchstr(getline('.'),'name_\d\+')|/end/s//\=submatch(0).'_'.@@/

個人的にはこれはかなり複雑ですが、選択肢があるのはいいことです。コマンドは、次の部分に分けることができます。

  • :g/name_\d\+name_ と数値に一致する各行でコマンドを実行します
  • getline('.')現在の行の文字列を返します
  • matchstr(getline('.'), 'name_\d\+')現在の行の一致する部分のみを返します
  • let @@ = matchstr(...)一致した部分をデフォルトレジスタに設定します
  • /end/s/:s一致する次の行でa を実行しますend
  • s//\=.../最後に使用されたパターンに一致し、express に置き換えます。
  • submatch(0).'_'.@@一致したパターン全体の後にアンダースコアと名前のないレジスタの内容が続く文字列を作成します。

次のトピックの詳細については、次を参照してください。

:h q
:h search-offset
:h :g
:h :let-@
:h registers
:h matchstr(
:h getline(
:h range
:h submatch(
于 2012-11-09T00:32:19.923 に答える