ハイパーマッスルエンジニア

Vim、ShellScriptについてよく書く

【Tips】Vimで先頭と末尾に文字を挿入する

コマンド一発で先頭と末尾に文字を挿入したいときってあるじゃん。
そんな時にどうするかって話。

方法

とりあえず結論から話すと以下のコマンドでいける。

:%s/^/先頭に入れたい文字/g | %s/$/行末に入れたい文字/g

パイプで繋げれば良かったんやな。 %sのところは'<,'>とか自由に変えてくれればいい。

どんなときに必要か

例えば以下のようなデータファイルがあるとする。

username.txt

Aaron
Adam
Adrian
Aidan
Alexander
Andrew
.....

これをプログラム中で配列に持ちたい時、例えばphpならこんな形にしたい。

<?php

$usernames = array(
    'Aaron',
    'Adam',
    'Adrian',
    'Aidan',
    'Alexander',
    'Andrew',
);

先頭と末尾にシングルクォートないしダブルクォートを挿入したい時って結構あると思うのですよ。

今まで

  1. Ctrl+Iで先頭に文字挿入
  2. gvで再度選択し$Aで行末に文字挿入

という流れでしていた。とっても面倒くさい。

全然思考のスピードでタイプできてないし、もっと長い行数の場合に一々最下行まで選択しに行かなければならないのがナンセンスだった。

f:id:rasukarusan:20190228214115g:plain
とっても面倒くさい

これから

シングルクォートを入れたい場合は以下で一撃だ。

:%s/^/'/g | %s/$/'/g

f:id:rasukarusan:20190228004427g:plain
コマンド版

ただこれだと打つのが面倒くさいし、全選択になってしまうので使い勝手が非常に悪い。

さらにこれから

範囲選択した時/しない時の両方に対応するため関数にした。

" 行頭と行末に文字列を挿入
" 範囲選択をしていない場合全範囲が対象となる
" ex.) InTH <div> <\/div>
function! s:insert_head_and_tail(...) range
    let head = a:1 " 行頭に入れたい文字列
    let tail = a:2 " 行末に入れたい文字列

    " 範囲選択中かで実行するコマンドが違うので分岐
    if a:firstline == a:lastline
        execute ':%s/^/'.head.'/g | %s/$/'.tail.'/g'
    else 
        execute ':'.a:firstline.','.a:lastline.'s/^/'.head.'/g | '.a:firstline.','.a:lastline."s/$/".tail.'/g'
    endif
endfunction
command! -nargs=+ -range InTH <line1>,<line2> call s:insert_head_and_tail(<f-args>)

f:id:rasukarusan:20190228213755g:plain
関数版

" 行頭に「"」、行末に「",」を挿入する時  
:InTH " ",

終わり

vim楽しいなあ。shell芸みたいに今回のも色々やり方あるんだろうなあ。
alias名が毎回適当になってしまうのが若干悩み。