スパム対策として書込み時にID/PWを要求されますが、ローマ字で ほげ/ホゲ で書き込めるようになります。

文字列操作方法まとめ

  • ページ: ScriptSample
  • カテゴリー: その他
  • 投稿日: 2010-01-03 00:59:20 (日)

メッセージ

文字列リテラル

echo "hello"
echo "hello\nworld"              " ダブルクォート文字列ではバックスラッシュで始まる特殊文字が使える
echo "\x56\x49\x4D"              " == "VIM"  2桁の16進文字コード
echo "\u3042"                    " == "あ"  4桁の16進の文字コード(現在の'encoding'の値に依存する)
echo 'hello\nworld'              " シングルクォート文字列では特殊文字は使えない

詳しくは
:h expr-quote
:h literal-string

比較 == はユーザーの環境によって動作が変わってしまうので、スクリプトでは ==# か ==? を使うとよいです。

s == y                            " 大文字小文字の区別はオプション 'ignorecase' 次第
s ==# y                           " 大文字小文字を区別する
s ==? y                           " 大文字小文字を区別しない

文字列の長さ

strlen("hoge")                    == 4
strlen("ほげ")                    == 6 (set encoding=utf-8 の場合。いずれにせよマルチバイト文字の長さは正しく出ない)

マルチバイト文字列対応 strlen
substitute ではマルチバイト文字も1文字と扱われることを利用する。

function! StringLength(str)
  return strlen(substitute(a:str, ".", "x", "g"))
endfunction

StringLength("ほげ")              == 2

部分文字列

strpart("abcdefg", 3, 2)          == "de"
strpart("abcdefg", -2, 4)         == "ab"
strpart("abcdefg", 5, 4)          == "fg"
strpart("abcdefg", 3)             == "defg"

マルチバイト対応 strpart

function! StringPart(str, start, len)
  let bend = byteidx(a:str, a:start + a:len) - byteidx(a:str, a:start)
  if bend < 0
    return strpart(a:str, byteidx(a:str, a:start))
  else
    return strpart(a:str, byteidx(a:str, a:start), bend)
  endif
endfunction
StringPart("こんにちは世界!", 2, 3)   == "にちは"

文字列を数値へ変換

str2nr("11")                      == 11   " 10進数
str2nr("11", 8)                   == 9    " 8進数
str2nr("11",16)                   == 17   " 16進数

str2float("4.5")                  == 4.5
str2float("1.2e4")                == 12000.0

大文字に変換

toupper("hoge")                   == "HOGE"

小文字に変換

tolower("HOGE")                   == "hoge"

sprintf

printf("%s=%d", "hoge", 123)      == "hoge=123"

分割してリストに

split("AAA,BBB,CCC", ",")         == ["AAA", "BBB, "CCC"]

文字列内から文字列を検索し、インデックスを返す

stridx("hogehoge", "g")           == 2   最初に現れる位置のバイトインデックス
strridx("hogehoge", "g")          == 6   最後に現れる位置のバイトインデックス

ある文字列が現れる回数

function! StringCount(str, ch)
  return StringLength(a:str) - StringLength(substitute(a:str, a:ch, '', 'g'))
endfunction

StringCount("ほげほげ", "ほ")       == 2

文字列を繰り返す

function! StringRepeat(str, count)
  let s = ""
  let i = 0
  while i < a:count
    let s = s . a:str
    let i = i + 1
  endwhile
  return s
endfunction

StringRepeat("*", 10)             == "**********"

置換

substitute("hoge", "og", "XX", "g") == "hXXe"
substitute("hoge", "OG", "XX", "g") == "hXXe"     " 'ignorecase' が適用される!
substitute("hoge", "og", "\n", "g") == "h\ne"     " 改行文字に置換
substitute("hoge", "h.*g", "&","g") == "hoge"     " 置換文字列における '&' は、:s と同様にマッチした文字列と解釈されてしまう!
substitute("hoge", "h.*g", '\&',"g") == "&e"      " バックスラッシュをつければOK
" 置換文字列には :s コマンドと同じく
" \0 \1 \2 ... \9 ~ \u \U \l \e \E
" が使える

正規表現マッチ

echo matchstr("hoge123", '[0-9]\+')   == "123"

" 部分マッチを取り出すにはmatchlist()を使う。
echo matchlist('acd', '\(a\)\?\(b\)\?\(c\)\?\(.*\)')
== ['acd', 'a', '', 'c', 'd', '', '', '', '', '']

" Vim 7 より前では matchlist() が使えないので、次のようにする。
" :h sscanf より

" 正規表現を設定
let mx='\(\f\+\),\s*\(\d\+\),\s*\(\d\+\)'
" 正規表現全体にマッチする部分を取り出す
let l = matchstr(line, mx)
" マッチ結果から各要素を取り出す
let file = substitute(l, mx, '\1', '')
let lnum = substitute(l, mx, '\2', '')
let col = substitute(l, mx, '\3', '')

エスケープ処理

" 指定した文字をバックスラッシュでエスケープする
escape('c:\program files\vim', ' \')   == 'c:\\program\ files\\vim'

" :exe を使うとき、ファイル名をエスケープする
let fname = '+some str%nge|name'
exe "edit " . fnameescape(fname)

" シェルに渡す引数をエスケープする
" exe "! " や system() を使う場合は必須です。
exe '!dir ' . shellescape(expand('<cfile>'), 1)
call system("chmod +w -- " . shellescape(expand("%")))

文字コードを変換する

iconv("あ", "utf-8", "cp932")     == <82><a0> (set encoding=utf-8 でないとそもそも "あ" が UTF-8 にならないので、結果が変わってしまうことに注意。

間違いがあったら指摘してください。
「○○はどうやるの」といった質問も言ってくれれば、書くようにします。
勝手に追加してくれてもいいです。


  • matchlist()を追加 -- 2010-01-06 18:56:29 (水)
  • StringLength?はchが1文字の場合にしか対応していないです。2文字以上に対応するには、StringLength?(a:ch)で割ればいいです。 -- 2012-01-06 23:45:40 (金)
  • StringLength?でなくてStringCount?だった… -- 2012-01-06 23:46:17 (金)



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2014-10-14 (火) 01:13:17 (1403d)