" Vimball Archiver by Charles E. Campbell, Jr., Ph.D. UseVimball finish doc/eregex.txt [[[1 431 *eregex.txt* File: eregex.vim, eregex_e.vim Author: AKUTSU toshiyuki Maintainer: othree Version: 2.56 Required: Vim version 6.1 Note: eregex.vim is used to convert regexp notation style. eregex_e.vim is used to map command for eregex.vim. 1. License |eregex-license-to-use| 2. Installation |eregex-installations| 3. Functions |eregex-functions| 4. Command |eregex-commands| 5. Usage |eregex-examples| 6. Keymap |eregex-keymappings| 7. Principle |eregex-principle| 8. Convert Table |eregex-table| 9. Options |eregex-options| 10. Multiline |eregex-multiline| 11. Limitation of Delimiter |eregex-limitation-of-delimiter| 12. About Vim Regexp |eregex-about-vimregex| ============================================================================== 1. License *eregex-license-to-use* Copyright of eregex.vim and eregex_e.vim belongs to AKUTSU toshiyuki. It is free to change and redistribute this script. You can think as an GPL License software. Author will not take any responsibility for damages due to using this script (eregex.vim, eregex_e.vim). ============================================================================== 2. Installation *eregex-installations* Open eregex.vba using Vim. And execute the following command. > :so % < ============================================================================== 3. Functions *eregex-functions* *eregex* *E2v()* E2v({extendedregex} [, {iISCDMm}]) Vim regexp notation will return. > :let vimregex = E2v('(?<=abc),\d+,(?=xzy)','i') :echo vimregex < Detail of option value can be found at |eregex-options| or |eregex-multiline| E2v("","V") Return eregex.vim version number > :echo E2v('','V') 248 < E2v({replacement}, {R1,R2,R3}) Return the "to" part of :S/pattern/to/ . > E2v('\r,\n,\&,&,\~,~', 'R1') => \n,\r,\&,&,\~,~ E2v('\r,\n,\&,&,\~,~', 'R2') => \r,\n,&,\&,~,\~ E2v('\r,\n,\&,&,\~,~', 'R3') => \n,\r,&,\&,~,\~ < ============================================================================== 4. Command *eregex-commands* *:E2v* :[range]E2v [iISCDMm] Extended regex To Vim regex. Replace each extended-regex in [range] with vim-style-regex. *:M* :M/eregex[/{offset} [iISCDMm]] Match :M/.*?<\/span>/Im ==> /\C\_.\{-}<\/span> *:S* :[range]S/{eregex}/{string}/[&cegpriISCDMm] Substitute :'<,'>S/(\d{1,3})(?=(\d\d\d)+($|\D))/\1,/g ==> :'<,'>s/\(\d\{1,3}\)\%(\(\d\d\d\)\+\($\|\D\)\)\@=/\1,/g *:G* *:G!* :[range]G/{eregex}/{command} :[range]G!/{eregex}/{command} Global :G/<<-(["'])?EOD\1/,/^\s*EOD\>/:left 8 ==> :g/<<-\(["']\)\=EOD\1/,/^\s*EOD\>/:left 8 *:V* :[range]V/{eregex}/{command} Vglobal ============================================================================== 5. Usage *eregex-examples* (1) :E2v command Change the regexp notation style of the cursor line. (\d{1,3})(?=(\d\d\d)+($|\D)) Move cursor to this line and execute :E2v command will change this line to the following result. \(\d\{1,3}\)\%(\(\d\d\d\)\+\($\|\D\)\)\@= (2) :M command > :M/.+?<\/Items>/Im < :normal! /\C\_.\{-1,}<\/Items> (3) :S command > :'<,'>S/(\d{1,3})(?=(\d\d\d)+($|\D))/\1,/g < :'<,'>s/\(\d\{1,3}\)\%(\(\d\d\d\)\+\($\|\D\)\)\@=/\1,/g 1 --> 1 12 --> 12 123 --> 123 1234 --> 1,234 12345 --> 12,345 123456 --> 123,456 1234567 --> 1,234,567 12345678 --> 12,345,678 123456789 --> 123,456,789 (4) :G command > :G/^begin$/+1;/^end$/-1:S/\l+/\U&/g < :g/^begin$/+1;/^end$/-1:s/\l\+/\U&/g begin hello world. hello world wide web. hello The Internet. end |begin | HELLO WORLD. | HELLO WORLD WIDE WEB. | HELLO THE INTERNET. |end (5) :V command Skipped. ============================================================================== 6. keymap *eregex-keymappings* You can add the following keymap to use / instead of type :/M nnoremap / :M/ nnoremap ? :M? nnoremap ,/ / nnoremap ,? / "/" will use :M/ to search. ",/" will use the original "/". -------------------- Add the following line to ~/.vimrc let eregex_replacement=3 will make :S have the following rules. :S/pattern/\r,\n,\&,&,\~,~/ :s/pattern/\n,\r,&,\&,~,\~/ +--------------------+-----------------------------+ | eregex_replacement | :S/pattern/\n,\r,&,\&,~,\~/ | +--------------------+-----------------------------+ | 0 | :s/pattern/\n,\r,&,\&,~,\~/ | | 1 | :s/pattern/\r,\n,&,\&,~,\~/ | | 2 | :s/pattern/\n,\r,\&,&,\~,~/ | | 3 | :s/pattern/\r,\n,\&,&,\~,~/ | +--------------------+-----------------------------+ ============================================================================== 7. Principle *eregex-principle* eregex.vim adopts the way of extended regex about "alternation", "repetition" and "grouping". ============================================================================== 8. Convert Table *eregex-table* Perl style on left side. Vim style ('magic') on right side. Alternation -------------------- :M/a|b /a\|b Repetition -------------------- :M/a* /a* :M/a+ /a\+ :M/a? /a\= :M/a*? /a\{-} :M/a+? /a\{-1,} :M/a?? /a\{-,1} :M/a{3,5} /a\{3,5} :M/a{3,} /a\{3,} :M/a{,5} /a\{,5} :M/a{3,5}? /a\{-3,5} :M/a{3,}? /a\{-3,} :M/a{,5}? /a\{-,5} Grouping -------------------- :M/(abc) /\(abc\) :M/(?:abc) /\%(abc\) :M/(?<=abc) /\%(abc\)\@<= :M/(?abc) /\%(abc\)\@> Special Characters -------------------- :M/\\,\|,\(,\),\{,\},\?,\+,\*,\[,\] /\\,|,(,),{,},?,+,\*,\[,\] :M/\^,\$ /\^,\$ Not support -------------------- \A, \b, \B, \G, \Z, \z Vim doesn't support these features. (?i:a) and (?-i) neither. Unusable Vim regexp notation -------------------- \%(re\) and square rackets ~ matches the last given substitute string \m 'magic' on for the following chars in the pattern \M 'magic' off for the following chars in the pattern \v the following chars in the pattern are "very magic" \V the following chars in the pattern are "very nomagic" \x hex digit: [0-9A-Fa-f] \\x[0-9A-Fa-f]{1,2} will change to character. \x82\xa0 => 'あ' ( shift-jis, cp932 ) But 0x00 and 0x0a and 0x08 will not change. Usable Vim regexp notations -------------------- \d, \D, \w, \W, \s, \S, \a, \A, \u, \U, \b, ... \<, \>, \zs, \ze \_[a-z], \%[abc], [[:alpha:]], \_., \_^, \_$ \%23l, \%23c, \%23v, \%# ============================================================================== 9. Special Option and Atom *eregex-options* Note: "^L" is \x0c eregex.vim Vim --------------------------------------- :M/a/i /\ca/ :M/\ca/ /\ca/ :M/a/I /\Ca/ :M/\Ca/ /\Ca/ :M/\s/S /[ \t\r\n^L] :M/\S/S /[^ \t\r^L] :M/[^az]/C /\_[^az]/ :M/\W/C /\_W/ :M/./D /\_./ :M/\s[^az]./M /[ \t\r\n^L]\_[^az]./ :M/\s[^az].\M/ Same as above. :M/\s[^az]./m /[ \t\r\n^L]\_[^az]\_./ :M/\s[^az].\m/ Same as above. +--------+------+--------------------------------------------------------+ | OPTION | ATOM | NOTE | +--------+------+--------------------------------------------------------+ | /i | \c | Case insensitive | | /I | \C | Case sensitive | +--------+------+--------------------------------------------------------+ | /S | | \s and \S becomes [ \t\r\n^L] and [^ \t\r^L] | | /C | | [] brackets will also match line break. | | /D | | Dot will match line break | +--------+------+--------------------------------------------------------+ | /M | \M | Use /S and /C . Partial multiline support | | /m | \m | Use /S, /C and /D . All support multiline | +--------+------+--------------------------------------------------------+ Note: (A) Option /iImM (B) \c, \C, \m, \M (C) (?i), (?I), (?m), (?M) If you use these at the same time. The priority will follow the order. If you use (?M) and (?m), \s in bracket will not work. ============================================================================== 10. Multiline *eregex-multiline* +-----+----------------------------------------------+--------------------+ | Num | eregex.vim => vim regex | ruby regex | +-----+----------------------------------------------+--------------------+ | (1) | :M/a\s[^az].z/ => /a\s[^az].z/ | /a[ \t][^az\n].z/ | +-----+----------------------------------------------+--------------------+ | | :M/a\s[^az].z/S => /a[ \t\r\n^L][^az].z/ | /a\s[^az\n].z/ | | | :M/a\s[^az].z/C => /a\s\_[^az].z/ | /a[ \t][^az].z/ | | | :M/a\s[^az].z/D => /a\s[^az]\_.z/ | /a[ \t][^az\n].z/m | +-----+----------------------------------------------+--------------------+ | (2) | :M/a\s[^az].z/M => /a[ \t\r\n^L]\_[^az].z/ | /a\s[^az].z/ | | (3) | :M/a\s[^az].z/m => /a[ \t\r\n^L]\_[^az]\_.z/ | /a\s[^az].z/m | +-----+----------------------------------------------+--------------------+ (1) is Vim style character class. (2) is Ruby style character class. (3) is Ruby style multiline. Note: In Vim style regexp, /[^az]/ will not match break line. But it is incorrect to to write /[^az\n]/ to point this out. /[^az\n]/ will match breakline. So we might use /[^ \t\r^L]/ instead of /[^ \t\r\n^L]/ . Just remember not write \n in [^...] . ============================================================================== 11. Limitation of Delimiter *eregex-limitation-of-delimiter* :M only support / and ? . :S, :G and :V supports /, #, @ . Usage and limitation are the same as :s, :g and :v Delimiter use @ will have some more limitation. For example: To replace "foo@bar.baz.co.jp" with "foo@hoge.co.jp" > :%s@\@foo\@hoge.co.jp@Ig < Will fail. \@ have special meaning in Vim regular expression . ============================================================================== 12. About Vim Regular Expression *eregex-about-vimregex* The following samples are all in a line with content "111,222,333". And use :S to execute replace. (1)Regular submatch 111,222,333 > :S/(\d+),(\d+),(\d+)/\=submatch(1) + submatch(2) + submatch(3) < 666 (2)Vim special feature Match data($&, &, matchdata) and submatch can be seperated. Use \zs and \ze . See :h /\zs for more information. 111,222,333 > :S/(\d+),\zs\d+\ze,(\d+)/\=submatch(1) + submatch(0) + submatch(2) < 111,666,333 (3) One more example 111,222,333 > :S/(\d+),\zs(\d+)\ze,(\d+)/\=submatch(1) + submatch(2) + submatch(3) < 111,666,333 Use \zs and \ze to control matchdata and submatch. (4) \_x \u is [A-Z] \_u is [A-Z\n] \_[A-Z] is [A-Z\n] Not uppercase characters and line break. \_U == \_[^A-Z] \_. is any character including line break. (5) Difference between ^ and \_^ or $ and \_$ Take $ for example $ is used in the following position (1) The last of regexp. (2) Just before ) . (3) Just before | . \_$ can be used anywhere to present as a line break. 111,222,333 > :S/(\d+),(\d+),(\d+)\zs\_$\ze/\=',' . (submatch(1) + submatch(2) + submatch(3)) < 111,222,333,666 If use $ instead of \_$ in this example will have different result. Note: \_^ and \_$ is totally different from /m option in Perl regexp. ============================================================================== 13. Changes revision 2.56 (1) Add support for "?" -- vim:ft=help: doc/eregex.jax [[[1 480 *eregex.jax* ファイル: eregex.vim, eregex_e.vim 作者: AKUTSU toshiyuki バージョン: 2.56 必要なもの: Vim version 6.1 かそれ以降。 説明: eregex.vim は、拡張正規表現を Vim の正規表現に変換します。 eregex_e.vim は、eregex.vim のコマンドを評価します。 1. 使用許諾 |eregex-license-to-use| 2. インストール |eregex-installations| 3. 関数 |eregex-functions| 4. コマンド |eregex-commands| 5. 使い方 |eregex-examples| 6. キーマップ |eregex-keymappings| 7. 原則 |eregex-principle| 8. 内部的な変換を表す一覧 |eregex-table| 9. 特殊なオプションとアトム |eregex-options| 10. マルチライン |eregex-multiline| 11. デリミタの制限 |eregex-limitation-of-delimiter| 12. Vim の正規表現について |eregex-about-vimregex| ============================================================================== 1. 使用許諾 *eregex-license-to-use* eregex.vim と eregex_e.vim の著作権は、作者である AKUTSU toshiyuki に 帰属します。しかし、改変、再配布は自由にしてかまいません。 # GPL とか分かんないのだ。(^^ )>> 作者は本スクリプト(eregex.vim, eregex_e.vim) を使用したことによって生じた いかなる損害について、一切の責任を負いません。 ============================================================================== 2. インストール *eregex-installations* 参考 |add-plugin| (1) UNIX/Linux $HOME/.vim/plugin/eregex.vim $HOME/.vim/plugin/eregex_e.vim $HOME/.vim/doc/eregex_j.txt それから、次のようにして helptags の再構築をします。 :helptags ~/.vim/doc これで、:h :E2v とかできます。 (2) MS-Windows eregex_j.txt は EUC-JP です。 MS-Windows の場合は予め ShiftJIS にしておいてください。 %HOME%\vimfiles\plugin\eregex.vim %HOME%\vimfiles\plugin\eregex_e.vim %HOME%\vimfiles\doc\eregex_j.txt または、 %VIM%\vimfiles\plugin\eregex.vim %VIM%\vimfiles\plugin\eregex_e.vim %VIM%\vimfiles\doc\eregex_j.vim それから、次のようにして helptags の再構築をします。 :helptags $HOME\vimfiles\doc または、 :helptags $VIM\vimfiles\doc これで、:h :E2v とかできます。 ============================================================================== 3. 関数 *eregex-functions* *eregex* *E2v()* E2v({extendedregex} [, {iISCDMm}]) 返り値は Vim の正規表現です。 > :let vimregex = E2v('(?<=abc),\d+,(?=xzy)','i') :echo vimregex \c\%(abc\)\@<=,\d\+,\%(xzy\)\@= < オプションの詳しい説明は |eregex-options| や |eregex-multiline| を見てください。 E2v("","V") 返り値は eregex.vim のバージョンです。 > :echo E2v('','V') 248 < E2v({replacement}, {R1,R2,R3}) これは、:S/pattern/to/ の "to" の部分で使う文字列を返します。 > E2v('\r,\n,\&,&,\~,~', 'R1') => \n,\r,\&,&,\~,~ E2v('\r,\n,\&,&,\~,~', 'R2') => \r,\n,&,\&,~,\~ E2v('\r,\n,\&,&,\~,~', 'R3') => \n,\r,&,\&,~,\~ < ============================================================================== 4. コマンド *eregex-commands* *:E2v* :[range]E2v [iISCDMm] Extended regex To Vim regex. Replace each extended-regex in [range] with vim-style-regex. *:M* :M/eregex[/{offset} [iISCDMm]] Match :M/.*?<\/span>/Im ==> /\C\_.\{-}<\/span> *:S* :[range]S/{eregex}/{string}/[&cegpriISCDMm] Substitute :'<,'>S/(\d{1,3})(?=(\d\d\d)+($|\D))/\1,/g ==> :'<,'>s/\(\d\{1,3}\)\%(\(\d\d\d\)\+\($\|\D\)\)\@=/\1,/g *:G* *:G!* :[range]G/{eregex}/{command} :[range]G!/{eregex}/{command} Global :G/<<-(["'])?EOD\1/,/^\s*EOD\>/:left 8 ==> :g/<<-\(["']\)\=EOD\1/,/^\s*EOD\>/:left 8 *:V* :[range]V/{eregex}/{command} Vglobal ============================================================================== 5. 使い方 *eregex-examples* (1) :E2v コマンド 次の拡張正規表現の行にカーソルを置く。 (\d{1,3})(?=(\d\d\d)+($|\D)) んで、:E2v を実行すると、次のようになる。 \(\d\{1,3}\)\%(\(\d\d\d\)\+\($\|\D\)\)\@= (2) :M コマンド > :M/.+?<\/Items>/Im < :normal! /\C\_.\{-1,}<\/Items> (3) :S コマンド > :'<,'>S/(\d{1,3})(?=(\d\d\d)+($|\D))/\1,/g < :'<,'>s/\(\d\{1,3}\)\%(\(\d\d\d\)\+\($\|\D\)\)\@=/\1,/g 1 --> 1 12 --> 12 123 --> 123 1234 --> 1,234 12345 --> 12,345 123456 --> 123,456 1234567 --> 1,234,567 12345678 --> 12,345,678 123456789 --> 123,456,789 (4) :G コマンド > :G/^begin$/+1;/^end$/-1:S/\l+/\U&/g < :g/^begin$/+1;/^end$/-1:s/\l\+/\U&/g begin hello world. hello world wide web. hello The Internet. end |begin | HELLO WORLD. | HELLO WORLD WIDE WEB. | HELLO THE INTERNET. |end (5) :V コマンド 説明省略。 ============================================================================== 6. キーマップ *eregex-keymappings* / で行なう通常の検索と :M/ を入れ替える。 .vimrc に以下を書く。 ( MS-Windows の場合 _vimrc か _gvimrc ) nnoremap / :M/ nnoremap ,/ / "/" で、:M/ になり、",/" で従来の "/" が使えます。 -------------------- ~/.vimrc の中に、 let eregex_replacement=3 を書いておくと :S コマンドの動作が次のように変わります。 :S/pattern/\r,\n,\&,&,\~,~/ :s/pattern/\n,\r,&,\&,~,\~/ +--------------------+-----------------------------+ | eregex_replacement | :S/pattern/\n,\r,&,\&,~,\~/ | +--------------------+-----------------------------+ | 0 | :s/pattern/\n,\r,&,\&,~,\~/ | | 1 | :s/pattern/\r,\n,&,\&,~,\~/ | | 2 | :s/pattern/\n,\r,\&,&,\~,~/ | | 3 | :s/pattern/\r,\n,\&,&,\~,~/ | +--------------------+-----------------------------+ ============================================================================== 7. 原則 *eregex-principle* eregex.vim において、 「選択」「繰り返し」「丸カッコ」は、拡張正規表現流 を採用する。 それ以外は Vim の正規表現に従う。 ============================================================================== 8. 内部的な変換を表す一覧 *eregex-table* 左には拡張正規表現を書き、右には Vim 流正規表現('magic')を書く。 選択 -------------------- :M/a|b /a\|b 繰り返し -------------------- :M/a* /a* :M/a+ /a\+ :M/a? /a\= :M/a*? /a\{-} :M/a+? /a\{-1,} :M/a?? /a\{-,1} :M/a{3,5} /a\{3,5} :M/a{3,} /a\{3,} :M/a{,5} /a\{,5} :M/a{3,5}? /a\{-3,5} :M/a{3,}? /a\{-3,} :M/a{,5}? /a\{-,5} 丸カッコ(パレン) -------------------- :M/(abc) /\(abc\) :M/(?:abc) /\%(abc\) :M/(?<=abc) /\%(abc\)\@<= :M/(?abc) /\%(abc\)\@> 文字そのもの -------------------- :M/\\,\|,\(,\),\{,\},\?,\+,\*,\[,\] /\\,|,(,),{,},?,+,\*,\[,\] :M/\^,\$ /\^,\$ 拡張正規表現で使えないもの -------------------- \A, \b, \B, \G, \Z, \z これらは全て Vim のものとして扱われる。 (?i:a) や (?-i) なども使えない。 Vim の正規表現で使えないもの -------------------- \%(re\) 等、パレン(丸カッコ) を使うもの全般。 ~ matches the last given substitute string \m 'magic' on for the following chars in the pattern \M 'magic' off for the following chars in the pattern \v the following chars in the pattern are "very magic" \V the following chars in the pattern are "very nomagic" \x hex digit: [0-9A-Fa-f] \\x[0-9A-Fa-f]{1,2} の場合、文字そのものに変換する。 \x82\xa0 => 'あ' ( shift-jis, cp932 ) ただし、0x00 と 0x0a と 0x08 は変換しません。 Vim の正規表現で使えるもの -------------------- 大抵使えます。(^^;) \d, \D, \w, \W, \s, \S, \a, \A, \u, \U, \b, ... \<, \>, \zs, \ze \_[a-z], \%[abc], [[:alpha:]], \_., \_^, \_$ \%23l, \%23c, \%23v, \%# など。 ============================================================================== 9. 特殊なオプションとアトム *eregex-options* Note: "^L" は \x0c eregex.vim Vim --------------------------------------- :M/a/i /\ca/ :M/\ca/ /\ca/ :M/a/I /\Ca/ :M/\Ca/ /\Ca/ :M/\s/S /[ \t\r\n^L] :M/\S/S /[^ \t\r^L] :M/[^az]/C /\_[^az]/ :M/\W/C /\_W/ :M/./D /\_./ :M/\s[^az]./M /[ \t\r\n^L]\_[^az]./ :M/\s[^az].\M/ 同上。 :M/\s[^az]./m /[ \t\r\n^L]\_[^az]\_./ :M/\s[^az].\m/ 同上。 +--------+------+--------------------------------------------------------+ | OPTION | ATOM | 説明 | +--------+------+--------------------------------------------------------+ | /i | \c | 大小文字の区別無し。 | | /I | \C | 大小文字の区別あり。 | +--------+------+--------------------------------------------------------+ | /S | | \s および \S を [ \t\r\n^L] や [^ \t\r^L] に変換する。 | | /C | | 補集合が改行にもマッチする。 | | /D | | ドットが改行にもマッチする。 | +--------+------+--------------------------------------------------------+ | /M | \M | /S と /C を行なう。 部分マルチライン。 | | /m | \m | /S と /C と /D を行なう。完全マルチライン。 | +--------+------+--------------------------------------------------------+ Note: (A) オプション /iImM (B) \c, \C, \m, \M (C) (?i), (?I), (?m), (?M) これらが同時に指定された場合、上の方が優先順位が高い。 ちなみに、(?M) と (?m) は、ブラケットの中の \s には適用されません。 ============================================================================== 10. マルチライン *eregex-multiline* とりあえず以下の表を見て。(^^;) +-----+----------------------------------------------+--------------------+ | Num | eregex.vim => vim regex | ruby regex | +-----+----------------------------------------------+--------------------+ | (1) | :M/a\s[^az].z/ => /a\s[^az].z/ | /a[ \t][^az\n].z/ | +-----+----------------------------------------------+--------------------+ | | :M/a\s[^az].z/S => /a[ \t\r\n^L][^az].z/ | /a\s[^az\n].z/ | | | :M/a\s[^az].z/C => /a\s\_[^az].z/ | /a[ \t][^az].z/ | | | :M/a\s[^az].z/D => /a\s[^az]\_.z/ | /a[ \t][^az\n].z/m | +-----+----------------------------------------------+--------------------+ | (2) | :M/a\s[^az].z/M => /a[ \t\r\n^L]\_[^az].z/ | /a\s[^az].z/ | | (3) | :M/a\s[^az].z/m => /a[ \t\r\n^L]\_[^az]\_.z/ | /a\s[^az].z/m | +-----+----------------------------------------------+--------------------+ (1) は、「文字クラス」が Vim 流。 (2) は、「文字クラス」が Ruby 流。 Vim 流に言えば、改行にマッチする所が増えたので、部分マルチライン。 Ruby 流に言えば、マルチラインでない。よってオプションは大文字の M 。 (3) は、いわゆる Ruby 流のマルチライン。 Note: Vim の正規表現では、/[^az]/ は改行にマッチしません。 改行にマッチしないことを明示して /[^az\n]/ と書く必要はありません。 /[^az\n]/ は意図に反して改行にもマッチします。 よって、本来 /[^ \t\r\n^L]/ とするべきところを、/[^ \t\r^L]/ に 変換している場合があります。 原則的に Vim では、[^...] の中に \n を書いてはいけません。 ============================================================================== 11. デリミタの制限 *eregex-limitation-of-delimiter* :M で使える区切り文字は / と ? だけです。 :S 、:G および :V で使える区切り文字は /, #, @ です。 これらの使用方法は :s 、:g 、:v と同じです。 制限も同様です。 区切り文字を @ にするといろいろ制限があります。 一見うまくいきそうに見えてダメな例。 "foo@bar.baz.co.jp" を "foo@hoge.co.jp" に置換しようとして、 > :%s@\@foo\@hoge.co.jp@Ig < は、エラーです。 Vim の正規表現で、\@ は特別な扱いを受けています。 ============================================================================== 12. Vim の正規表現について *eregex-about-vimregex* 以下 カーソルを "111,222,333" の行に置いて、:S... を実行してください。 (1)通常のサブマッチ。 111,222,333 > :S/(\d+),(\d+),(\d+)/\=submatch(1) + submatch(2) + submatch(3) < 666 (2)Vim 独自機能。 マッチデータ($&, &, matchdata) と、サブマッチを分離できます。 \zs と \ze を使う。 See :h /\zs 111,222,333 > :S/(\d+),\zs\d+\ze,(\d+)/\=submatch(1) + submatch(0) + submatch(2) < 111,666,333 (3) 以下の方が分かりやすいかも。 111,222,333 > :S/(\d+),\zs(\d+)\ze,(\d+)/\=submatch(1) + submatch(2) + submatch(3) < 111,666,333 \zs と \ze を使うと、マッチデータに含まれないサブマッチを操作できます。 (4) \_x の機能。 \u で [A-Z] を表す。 \_u で [A-Z\n] を表す。 \_[A-Z] は [A-Z\n] と同じ。 大文字以外で改行を含む文字。 \_U == \_[^A-Z] \_. は改行を含む任意の文字。 (5) ^ と \_^ および $ と \_$ の違い。 $ を例にとります。 通常 $ は (1)正規表現の一番最後。 (2) ) の直前。 (3) | の直前。 にある場合だけ行末を表す。 ところが任意の場所で行末を表せるのが \_$ 。 111,222,333 > :S/(\d+),(\d+),(\d+)\zs\_$\ze/\=',' . (submatch(1) + submatch(2) + submatch(3)) < 111,222,333,666 ここで使っている \_$ の代わりに $ を使っても意図した結果になりません。 Note: \_^ と \_$ は perl の /m オプションとは全然違います。 ============================================================================== 13. 履歴 revision 2.55 (1) E2v() にバージョン番号や、sub-replace-special の置換を加えた。 (2) \v を 0x0b に置換するようにした。 (3) :M/pattern/ でマッチしなくても、@/ を更新した。 revision 2.35 (1) オプション S,C,D,M,m の追加と変更。 revision 1.4x (1) :S/\x2f/\\/g とかすると、:s///\\/g に変換してしまうバグ修正。 (2) エスケープされたデリミタを検索履歴ではアンエスケープした。 デリミタが '@' の場合を除く。 (3) オプション m の修正。 revision 1.13 :G で ! を使えるようにした。 revision 1.1.1.21 :S の /c オプションで確認のプロンプトが見えなくなってしまう問題修正。 -- vim:ft=help: plugin/eregex_e.vim [[[1 17 " $Id: eregex_e.vim,v 1.40 2003-06-03 18:25:59+09 ta Exp ta $ " An evaluater for eregex.vim if exists('g:eregex_evaluater_cmd') && exists('g:eregex_evaluater_how_exe') if g:eregex_evaluater_how_exe==0 " :s silently exec, handle errmsg silent! exec g:eregex_evaluater_cmd elseif g:eregex_evaluater_how_exe==1 " :s invoked by :g and " :s with confirm option exec g:eregex_evaluater_cmd elseif g:eregex_evaluater_how_exe==2 ":g redraw exec g:eregex_evaluater_cmd endif endif plugin/eregex.vim [[[1 1031 "============================================================================= " File: eregex.vim and eregex_e.vim " Author: AKUTSU toshiyuki " Requirements: Vim version 6.1 and later. " Description: eregex.vim is a converter from extended regex to vim regex " eregex_e.vim is an evaluater for command of eregex.vim " The meaning of extended regex is pseudo ruby/perl-style regex. " Previous $Id: eregex.vim,v 2.55 2003-09-19 17:39:41+09 ta Exp $ " $Id: eregex.vim,v 2.56 2010-10-18 11:59:41+08 ta Exp $ " Note: English isn't my mother tongue. "============================================================================= " Principle: " eregex.vim adopts the way of extended regex about "alternation", " "repetition" and "grouping". " As for those things, the way of Vim regex is adopted. " You can use '\_^', '\zs', '\<', '\%<23c', '\_u', etc in extended regex. "============================================================================= " Functions: " " E2v({extended_regex} [, {iISCDMm}]) " The result is a String, which is vim style regex. " " :let vimregex = E2v('(?<=abc),\d+,(?=xzy)','i') " :echo vimregex " \c\%(abc\)\@<=,\d\+,\%(xzy\)\@= " " E2v('','V') " The result is a Number, which is eregex.vim version. " " :echo E2v('','V') " 238 " " E2v({replacement} ,{R1,R2,R3}) " The result is a String, which is used for the "to" part of :S/from/to/ " " E2v('\r,\n,\&,&,\~,~', 'R1') => \n,\r,\&,&,\~,~ " E2v('\r,\n,\&,&,\~,~', 'R2') => \r,\n,&,\&,~,\~ " E2v('\r,\n,\&,&,\~,~', 'R3') => \n,\r,&,\&,~,\~ " "============================================================================= " Commands: " " :[range]E2v [iISCDMm] " Extended regex To Vim regex. " Replace each extended-regex in [range] with vim-style-regex. " " :M/eregex/[offset][iISCDMm] " Match. " :M/.*?<\/span>/Im " => /\C\_.\{-}<\/span> " " :[range]S/eregex/replacement/[&cegpriISCDMm] " Substitute. " :'<,'>S/(\d{1,3})(?=(\d\d\d)+($|\D))/\1,/g " => :'<,'>s/\(\d\{1,3}\)\%(\(\d\d\d\)\+\($\|\D\)\)\@=/\1,/g " " :[range]G/eregex/command " Global. " :G/<<-(["'])?EOD\1/,/^\s*EOD\>/:left 8 " => :g/<<-\(["']\)\=EOD\1/,/^\s*EOD\>/:left 8 " " :[range]V/eregex/command " Vglobal " "============================================================================= " Tips And Configuration: " " Put the following commands in your ~/.vimrc to replace normal / with :M/ " " nnoremap / :M/ " nnoremap ,/ / " " v238, v243 " If you put 'let eregex_replacement=3' in your ~/.vimrc, " " :S/pattern/\r,\n,\&,&,\~,~/ will be converted to :s/pattern/\n,\r,&,\&,~,\~/ " " +--------------------+-----------------------------+ " | eregex_replacement | :S/pattern/\n,\r,&,\&,~,\~/ | " +--------------------+-----------------------------+ " | 0 | :s/pattern/\n,\r,&,\&,~,\~/ | " | 1 | :s/pattern/\r,\n,&,\&,~,\~/ | " | 2 | :s/pattern/\n,\r,\&,&,\~,~/ | " | 3 | :s/pattern/\r,\n,\&,&,\~,~/ | " +--------------------+-----------------------------+ " See :h sub-replace-special " "============================================================================= " Options: " Note: "^L" is "\x0c". " " "i" ignorecase " "I" noignorecase " "S" convert "\s" to "[ \t\r\n^L]" and also convert "\S" to "[^ \t\r^L]" " Mnemonic: extended spaces " "C" convert "[^az]" to "\_[^az]" and also convert "\W" to "\_W". " Mnemonic: extended complement " Vim's "[^az]" matches anything but "a", "z", and a newline. " "D" convert "." to "\_." " Mnemonic: extended dot " Normally, "." matches any character except a newline. " "M" partial multiline; do both "S" and "C". " In other words, It is not "multiline" in ruby way. " "m" full multiline; do all the above conversions "S", "C" and "D". " In other words, It is just "multiline" in ruby way. " "+-----+----------------------------------------------+--------------------+ "| Num | eregex.vim => vim regex | ruby regex | "+-----+----------------------------------------------+--------------------+ "| (1) | :M/a\s[^az].z/ => /a\s[^az].z/ | /a[ \t][^az\n].z/ | "+-----+----------------------------------------------+--------------------+ "| | :M/a\s[^az].z/S => /a[ \t\r\n^L][^az].z/ | /a\s[^az\n].z/ | "| | :M/a\s[^az].z/C => /a\s\_[^az].z/ | /a[ \t][^az].z/ | "| | :M/a\s[^az].z/D => /a\s[^az]\_.z/ | /a[ \t][^az\n].z/m | "+-----+----------------------------------------------+--------------------+ "| (2) | :M/a\s[^az].z/M => /a[ \t\r\n^L]\_[^az].z/ | /a\s[^az].z/ | "| (3) | :M/a\s[^az].z/m => /a[ \t\r\n^L]\_[^az]\_.z/ | /a\s[^az].z/m | "+-----+----------------------------------------------+--------------------+ " " Note: " As for "\s", "[^az]" and ".", "M" and "m" options make " eregex.vim-regexen compatible with ruby/perl-style-regexen. " Note: " Vim's "[^az]" doesn't match a newline. " Contrary to the intention, "[^az\n]" matches a newline. " The countermeasure is to convert "[^\s]" to "[^ \t\r^L]" with " multiline. " "============================================================================= " pseudo ruby/perl-style regexen. " " available extended regexen: " alternation: " "a|b" " repetition: " "a+", "a*", "a?", "a+?", "a*?", "a??," " "a{3,5}", "a{3,}", "a{,5}", "a{3,5}?", "a{3,}?", "a{,5}?" " grouping: " "(foo)", "(?:foo)", "(?=foo)", "(?!foo)", "(?<=foo)", " "(?foo)" " modifiers: " "(?I)", "(?i)", "(?M)", "(?m)", "(?#comment)" " " Note: " The use of "\M" or "\m" is preferable to the use of "(?M)" or "(?m)". " "(?M)" and "(?m)" can't expand "\s" in brackets to " \t\r\n^L". " " not available extended regexen: " "\A", "\b", "\B", "\G", "\Z", "\z", " "(?i:a)", "(?-i)", "(?m:.)", " There are no equivalents in vim-style regexen. " " special atoms: " "\C" noignorecase " "\c" ignorecase " "\M" partial multiline " "\m" full multiline " " For example: " :M/a\s[^az].z/M => /a[ \t\r\n^L]\_[^az].z/ " :M/a\s[^az].z\M/ => /a[ \t\r\n^L]\_[^az].z/ " :M/a\s[^az].z/m => /a[ \t\r\n^L]\_[^az]\_.z/ " :M/a\s[^az].z\m/ => /a[ \t\r\n^L]\_[^az]\_.z/ " The order of priority: " [A] /IiMm, [B] \C, \c, \M, \m, [C] (?I), (?i), (?M), (?m) " " many other vim-style regexen available: " "\d", "\D", "\w", "\W", "\s", "\S", "\a", "\A", " "\u", "\U", "\b" " "\<", "\>" " "\zs", "\ze" " "\_[a-z]", "\%[abc]", "[[:alpha:]]" " "\_.", "\_^", "\_$" " "\%23l", "\%23c", "\%23v", "\%#" " and so on. See :h /ordinary-atom " " misc: " Convert "\xnn" to char except "\x00", "\x0a" and "\x08". " "\x41\x42\x43" => "ABC" " "\x2a\x5b\x5c" => "\*\[\\" " Expand atoms in brackets. " "[#$\w]" => "[#$0-9A-Za-z_]" " " "\f" in brackets is converted to "\x0c". " but "\f" out of brackets is a class of filename characters. " " eregex.vim expansion of atoms and its meaning. " +-------+----------------------+----------------------+ " | atom | out of brackets | in brackets | " +-------+----------------------+----------------------+ " | \a | alphabetic char | alphabetic char | " | \b | \x08 | \x08 | " | \e | \x1b | \x1b | " | \f | filename char | \x0c | " | \n | \x0a | \x0a | " | \r | \x0d | \x0d | " | \s | [ \t] or [ \t\r\n\f] | " \t" or " \t\r\n\f" | " | \t | \x09 | \x09 | " | \v | \x0b | \x0b | " | \xnn | hex nn | hex nn | " +-------+----------------------+----------------------+ " "============================================================================= if version < 601 | finish | endif if exists("loaded_eregex") finish endif let loaded_eregex=1 "============================================================================= "Commands And Mappings: command! -nargs=? -range E2v :,call ExtendedRegex2VimRegexLineWise() command! -nargs=? M :call Ematch() "command! -nargs=? -range S :,call Esubstitute() command! -nargs=? -range S :,call Esubstitute() :noh command! -nargs=? -range=% -bang G :,call Eglobal(, ) command! -nargs=? -range=% V :,call Evglobal() "============================================================================= "Script Variables: let s:eglobal_working=0 "-------------------- let s:ch_with_backslash=0 let s:ch_posix_charclass=1 let s:ch_brackets=2 let s:ch_braces=3 let s:ch_parentheses_option=4 let s:ch_parentheses=5 let s:re_factor{0}='\\\%([^x_]\|x\x\{0,2}\|_[.$^]\=\)' let s:re_factor{1}= '\[:\%(alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|' . \ 'space\|upper\|xdigit\|return\|tab\|escape\|backspace\):\]' let s:re_factor{2}='\[\%([^^][^]]*\|\^.[^]]*\)\]' let s:re_factor{3}='{[0-9,]\+}?\=' "v141 "let s:re_factor{4}='(?[iISCDMm]\{1,7})' let s:re_factor{4}='(?[iImM]\{1,2})' let s:re_factor{5}='(\(?:\|?=\|?!\|?<=\|?\|?[-#ixm]\)\=[^()]*)' let s:re_factor_size=6 "-------------------- let s:mark_left="\" . strftime("%X") . ":" . strftime("%d") . "\" let s:mark_right="\" . strftime("%X") . ":" . strftime("%d") . "\" let s:stack_size=0 let s:invert=0 let s:multiline=0 let s:ignorecase=0 "v220 let s:re_unescaped='\%(\\\)\@\)\=') let fct = substitute(fct, '(\(?:\|?=\|?!\|?<=\|?\)\=', "", "") let fct = strpart(fct, 0, strlen(fct)-1) let fct = s:ReplaceRemainFactorWithVimRegexFactor(fct) if kakko ==# '(' let fct = '\(' . fct . '\)' elseif kakko ==# '(?:' let fct = '\%(' . fct . '\)' elseif kakko ==# '(?=' let fct = '\%(' . fct . '\)\@=' elseif kakko ==# '(?!' let fct = '\%(' . fct . '\)\@!' elseif kakko ==# '(?<=' let fct = '\%(' . fct . '\)\@<=' elseif kakko ==# '(?' let fct = '\%(' . fct . '\)\@>' else let fct = ":BUG:" endif endif let s:stack{s:stack_size} = fct let s:stack_size = s:stack_size + 1 endfunction "end s:Push() "----------------------------------------------------------------------------- function! s:ExpandAtomsInBrackets(bracket) let bracket = a:bracket let re_mark = s:mark_left . '\d\+' . s:mark_right let re_snum = s:mark_left . '\(\d\+\)' . s:mark_right "v120 let has_newline=0 "v216,v249 let complement=(bracket =~# '^\[^') let searchstart = 0 let mtop = match(bracket, re_mark, searchstart) while mtop >= 0 let mstr = matchstr(bracket, re_mark, searchstart) let snum = substitute(mstr, re_snum, '\1', "") + 0 "v222 let fct = s:stack{snum} "exclude, \e=0x1b, \b=0x08, \r=0x0d, \t=0x09 if fct =~# '^\\[adfhlosuwx]$' let chr = fct[1] if chr ==# 'a' let fct='A-Za-z' elseif chr ==# 'd' let fct='0-9' elseif chr ==# 'f' "let fct=nr2char(0x0c) let fct="\x0c" elseif chr ==# 'h' let fct='A-Za-z_' elseif chr ==# 'l' let fct='a-z' elseif chr ==# 'o' let fct='0-7' elseif chr ==# 's' "v141 if s:extended_spaces==1 "v217 if (s:countermeasure==1) && (complement==1) let fct=" \\t\\r\x0c" else let fct=" \\t\\r\\n\x0c" endif let has_newline=1 else let fct=' \t' endif elseif chr ==# 'u' let fct='A-Z' elseif chr ==# 'w' let fct='0-9A-Za-z_' elseif chr ==# 'x' let fct='0-9A-Fa-f' endif let s:stack{snum}=fct else "v120 if fct ==# '\n' "If there is only "\n" of inside of the brackets. "It becomes the same as "\_.". let has_newline=1 "v219 elseif fct ==# '-' " '-' converted from \xnn "If there is '-' in the beginning of the brackets and the end. "Unnecessary '\' is stuck. let s:stack{snum}='\-' "v237 elseif fct ==# '\[' " '\[' converted from \xnn let s:stack{snum}='[' endif endif let searchstart = mtop + strlen(mstr) let mtop = match(bracket, re_mark, searchstart) endwhile "v120 if (complement==1) && (has_newline==0) let bracket = s:mark_complements . bracket endif return bracket endfunction "end ExpandAtomsInBrackets() "----------------------------------------------------------------------------- function! s:Pop() if s:stack_size <= 0 | return "" | endif let s:stack_size = s:stack_size - 1 return s:stack{s:stack_size} endfunction "----------------------------------------------------------------------------- " Debug: function! s:UnletStack() let i = 0 while exists("s:stack" . i) exec "unlet s:stack" . i let i = i + 1 endwhile let s:stack_size = 0 endfunction " Debug: "function! EachStack() " let lineno = line(".") " let i = 0 " while exists("s:stack" . i) " call append(lineno + i, i . " -> " . s:stack{i}) " let i = i + 1 " endwhile "endfunction "----------------------------------------------------------------------------- function! s:ReplaceExtendedRegexFactorWithNumberFactor(extendedregex) let halfway = a:extendedregex let s:stack_size = 0 let i=0 let id_num=0 while i < s:re_factor_size "CASESENSE: let regex = '\C' . s:re_factor{i} let mtop = match(halfway, regex) while mtop >= 0 let factor = matchstr(halfway, regex) let pre_match = strpart(halfway, 0, mtop) let post_match= strpart(halfway, mtop + strlen(factor)) let halfway = pre_match . s:mark_left . id_num . s:mark_right . post_match "END: call s:Push( factor, i ) let id_num = id_num + 1 let mtop = match(halfway, regex) endwhile let i = i + 1 endwhile return halfway endfunction "end s:ReplaceExtendedRegexFactorWithNumberFactor() "----------------------------------------------------------------------------- function! s:ReplaceRemainFactorWithVimRegexFactor(halfway) let halfway = a:halfway " minimal match, not greedy let halfway = substitute(halfway, '+?', '\\{-1,}', 'g') let halfway = substitute(halfway, '\*?', '\\{-}', 'g') let halfway = substitute(halfway, '??', '\\{-,1}', 'g') "-------------------- let halfway = substitute(halfway, '+', '\\+', 'g') let halfway = substitute(halfway, '?', '\\=', 'g') "-------------------- let halfway = substitute(halfway, '|', '\\|', 'g') "-------------------- let halfway = substitute(halfway, '\~', '\\&', 'g') "-------------------- "v141 if s:extended_dots==1 let halfway = substitute(halfway, '\.', '\\_.', 'g') endif return halfway endfunction "end s:ReplaceRemainFactorWithVimRegexFactor() "----------------------------------------------------------------------------- function! s:ReplaceNumberFactorWithVimRegexFactor(halfway) let vimregex = a:halfway let i = s:stack_size while i > 0 let i = i - 1 let factor = s:Pop() let str_mark = s:mark_left . i . s:mark_right let vimregex = s:ReplaceAsStr(vimregex, str_mark, factor) endwhile "Debug: call s:UnletStack() "v221 "v120 if stridx(vimregex, s:mark_complements)!=-1 "v141 if s:extended_complements==1 "there isn't \_ before [^...]. " [^...] doesn't contain \n. let re='\C\%(\%(\\\)\@ 0 let tmp = (s:ignorecase==1) ? '\c' : '\C' let vimregex = tmp . vimregex endif "if &magic==0 " let vimregex = '\m' . vimregex "endif return vimregex endfunction "end s:ReplaceNumberFactorWithVimRegexFactor() "============================================================================= "Main: function! s:ExtendedRegex2VimRegex(extendedregex, ...) "v141 let s:ignorecase=0 let s:multiline=0 let s:extended_spaces=0 let s:extended_complements=0 let s:extended_dots=0 if a:0==1 "v238,v243 if a:1 =~# 'R[0-3]' return s:ExchangeReplaceSpecials(a:extendedregex, matchstr(a:1, 'R\zs[0-3]')) "v240 elseif a:1 ==# 'V' return s:version endif call s:SetModifiers(a:1) endif "v240 moved here if strlen(a:extendedregex)==0 return "" endif "v141 let eregex=a:extendedregex "v221 let mods = matchstr(eregex, '\C' . s:re_escaped . '[Mm]') let mods = mods . matchstr(eregex, '\C' . s:re_escaped . '[Cc]') if mods !=# '' let mods = substitute(mods, '\CC', 'I',"g") let mods = substitute(mods, '\Cc', 'i',"g") call s:SetModifiers(mods) let re='\C' . s:re_escaped . '[MmCc]' let eregex=substitute(eregex, re, '', "g") endif "-------------------- let halfway = s:ReplaceExtendedRegexFactorWithNumberFactor(eregex) let halfway = s:ReplaceRemainFactorWithVimRegexFactor(halfway) let vimregex = s:ReplaceNumberFactorWithVimRegexFactor(halfway) "v221 return vimregex endfunction "end s:ExtendedRegex2VimRegex() "----------------------------------------------------------------------------- function! s:ExtendedRegex2VimRegexLineWise(...) range if a:1 ==# '--version' echo "$Id: eregex.vim,v 2.56 2003-09-19 17:39:41+09 ta Exp $" return endif let modifiers= a:1 let i = a:firstline while i <= a:lastline call setline(i, s:ExtendedRegex2VimRegex(getline(i), modifiers)) let i = i + 1 endwhile endfunction "end s:ExtendedRegex2VimRegexLineWise() "----------------------------------------------------------------------------- "Public: function! E2v(extendedregex, ...) if a:0==0 return s:ExtendedRegex2VimRegex(a:extendedregex) endif return s:ExtendedRegex2VimRegex(a:extendedregex, a:1) endfunction "end E2v() "----------------------------------------------------------------------------- function! s:Ematch(...) if strlen(a:1) <= 1 | return | endif let string = a:1 let delim=string[0] if delim !=# '/' && delim !=# '?' let v:errmsg= "The delimiter `" . delim . "' isn't available, use `/' ." echo v:errmsg return endif let rxp ='^delim\([^delim\\]*\%(\\.[^delim\\]*\)*\)' . \ '\(delim.*\)\=$' let rxp=substitute(rxp, 'delim', delim, "g") let regex = substitute(string, rxp, '\1',"") let offset= substitute(string, rxp, '\2', "") "-------------------- let modifiers='' "v141 if offset =~# '[' . s:str_modifiers . ']' let modifiers = substitute(offset, '\C[^' . s:str_modifiers . ']\+', "", "g") let offset = substitute(offset, '\C[' . s:str_modifiers . ']\+', "", "g") endif let regex = s:ExtendedRegex2VimRegex(regex, modifiers) "v130 "set s:bakregex let regex = s:EscapeAndUnescape(regex, delim) "-------------------- if offset==# '' let offset = delim endif let cmd = 'normal! ' . delim . regex . offset . "\" let v:errmsg='' silent! exec cmd if (v:errmsg !~# '^E\d\+:') || (v:errmsg =~# '^E486:') "v130 if s:bakregex !=# '' let @/ = s:bakregex endif endif if v:errmsg ==# '' redraw! else echo 'M' . a:1 echo v:errmsg endif endfunction "end s:Ematch() "----------------------------------------------------------------------------- function! s:Esubstitute(...) range if strlen(a:1) <= 1 | return | endif let string = a:1 let delim = s:GetDelim(string[0]) if delim==# '' | return | endif let rxp ='^delim\([^delim\\]*\%(\\.[^delim\\]*\)*\)delim\([^delim\\]*\%(\\.[^delim\\]*\)*\)' . \ '\(delim.*\)\=$' let rxp=substitute(rxp, 'delim', delim, "g") if string !~# rxp if s:eglobal_working==0 echo 'Invalid arguments S' . a:1 endif return endif let regex = substitute(string, rxp, '\1',"") let replacement = substitute(string, rxp, '\2', "") let options = substitute(string, rxp, '\3',"") "-------------------- "v141 let modifiers='' if options =~# '[' . s:str_modifiers . ']' let modifiers = substitute(options, '\C[^' . s:str_modifiers . ']\+', "", "g") let options = substitute(options, '\C[SCDmM]', "", "g") endif let regex = s:ExtendedRegex2VimRegex(regex, modifiers) "v130 "set s:bakregex let regex = s:EscapeAndUnescape(regex, delim) "v238, v243 if (s:eregex_replacement > 0) && (strlen(replacement) > 1) let replacement = s:ExchangeReplaceSpecials(replacement, s:eregex_replacement) endif "-------------------- if options ==# '' let options = delim endif let cmd = a:firstline . ',' . a:lastline . 's' . delim . regex . delim . replacement . options "Evaluater: let g:eregex_evaluater_how_exe = s:eglobal_working if g:eregex_evaluater_how_exe==0 let v:statusmsg='' let v:errmsg='' endif let confirmoption = (options =~# 'c') if confirmoption==1 "with confirm option. let g:eregex_evaluater_how_exe=1 endif let g:eregex_evaluater_cmd = cmd runtime plugin/eregex_e.vim if g:eregex_evaluater_how_exe==0 || confirmoption==1 unlet! g:eregex_evaluater_cmd "v130 if s:bakregex !=# '' let @/ = s:bakregex endif if confirmoption==0 if v:errmsg==# '' if v:statusmsg !=# '' echo v:statusmsg endif else echo v:errmsg endif endif endif endfunction "end s:Esubstitute() "----------------------------------------------------------------------------- function! s:Eglobal(bang, ...) range if strlen(a:1)<=1 | return | endif let string=a:1 let delim = s:GetDelim(string[0]) if delim==#'' | return | endif "-------------------- let re_pattern = substitute('[^delim\\]*\%(\\.[^delim\\]*\)*', 'delim', delim,"g") let re_offset = '\%([-+0-9]\d*\|\.[-+]\=\d*\)' let re_sep = '[,;]' let re_command = '[^,;].*' let re_command_less = '\_$' let re_end = '\%(' . re_sep . '\|' . re_command . '\|' . re_command_less . '\)' "-------------------- let toprxp0 = '^' . delim . '\(' . re_pattern . '\)\(' . delim . re_offset . re_sep . '\)' let toprxp1 = '^' . delim . '\(' . re_pattern . '\)\(' . delim . re_sep . '\)' let toprxp2 = '^' let endrxp0 = delim . '\(' . re_pattern . '\)\(' . delim . re_offset . re_end . '\)' let endrxp1 = delim . '\(' . re_pattern . '\)\(' . delim . re_end . '\)' let endrxp2 = delim . '\(' . re_pattern . '\)' . re_command_less "-------------------- let mtop = -1 let j = 0 while j < 3 let i = 0 while i < 3 let regexp = toprxp{j} . endrxp{i} let mtop = match(string, regexp) if mtop>=0 | break | endif let i = i + 1 endwhile if mtop>=0 | break | endif let j = j + 1 endwhile if mtop<0 | return | endif "-------------------- if a:bang==# '!' let s:invert=1 endif let cmd = (s:invert==0) ? 'g' : 'v' let s:invert=0 let cmd = a:firstline . ',' . a:lastline . cmd let globalcmd = '' if j == 2 let pattern1 = substitute(string, regexp, '\1', "") let strright = delim if i < 2 let strright = substitute(string, regexp, '\2', "") endif let pattern1 = s:ExtendedRegex2VimRegex(pattern1) "v130 let pattern1 = s:EscapeAndUnescape(pattern1, delim) let globalcmd = cmd . delim . pattern1 . strright else let pattern1 = substitute(string, regexp, '\1', "") let strmid = substitute(string, regexp, '\2',"") let pattern2 = substitute(string, regexp, '\3', "") let strright = delim if i < 2 let strright = substitute(string, regexp, '\4', "") endif let pattern1 = s:ExtendedRegex2VimRegex(pattern1) let pattern2 = s:ExtendedRegex2VimRegex(pattern2) "v130 let pattern1 = s:EscapeAndUnescape(pattern1, delim) let pattern2 = s:EscapeAndUnescape(pattern2, delim) let globalcmd = cmd . delim . pattern1 . strmid . delim . pattern2 . strright endif "-------------------- "Evaluater: let s:eglobal_working=1 let g:eregex_evaluater_how_exe=2 let g:eregex_evaluater_cmd = globalcmd runtime plugin/eregex_e.vim let s:eglobal_working=0 "let g:eregex_evaluater_how_exe=0 unlet! g:eregex_evaluater_cmd endfunction "end s:Eglobal() "----------------------------------------------------------------------------- function! s:Evglobal(...) range let s:invert=1 let cmd = a:firstline . ',' . a:lastline . 'G' . a:1 exec cmd endfunction "end s:Evglobal() "----------------------------------------------------------------------------- function! s:GetDelim(str) let valid = '[/@#]' let delim = a:str[0] if delim =~# valid return delim endif let v:errmsg = "The delimiter `" . delim . "' isn't available, use " . valid echo v:errmsg return '' endfunction "end s:GetDelim() "============================================================================= "v130 "called from Ematch(), Esubstitute(), Eglobal() "use s:re_unescaped, s:re_escaped, s:bakregex function! s:EscapeAndUnescape(vimregex, delim) let vimregex = a:vimregex let s:bakregex= a:vimregex if a:delim ==# '@' return vimregex endif if s:bakregex =~# s:re_escaped . a:delim " \/ or \# exists let s:bakregex = substitute(vimregex, s:re_escaped . a:delim, a:delim, "g") endif if vimregex =~# s:re_unescaped . a:delim " / or # exists let vimregex = substitute(vimregex, s:re_unescaped . a:delim, '\\' . a:delim, "g") endif return vimregex endfunction "end s:EscapeAndUnescape() "============================================================================= "v141 "called from only s:ExtendedRegex2VimRegex() function! s:SetModifiers(mods) "v221 if s:ignorecase==0 if a:mods =~# 'i' let s:ignorecase=1 elseif a:mods =~# 'I' let s:ignorecase=2 endif endif "v221 if s:multiline==0 if a:mods =~? 'm' let s:extended_spaces=1 let s:extended_complements=1 if a:mods =~# 'M' "partial multiline let s:multiline=1 else "full multiline let s:extended_dots=1 let s:multiline=2 endif endif endif if a:mods =~# 'S' let s:extended_spaces=1 endif if a:mods =~# 'C' let s:extended_complements=1 endif if a:mods =~# 'D' let s:extended_dots=1 endif endfunction "End: s:SetModifiers(mods) "============================================================================= "v238, function! s:ExchangeReplaceSpecials(replacement, sort) let rs=a:replacement "v243,v246 if (rs !~# '[&~]\|\\[rnx]') || (rs =~# '^\\=') return rs endif if (a:sort % 2)==1 let rs=substitute(rs, '\C' . s:re_escaped . 'r', '\\R', "g") let rs=substitute(rs, '\C' . s:re_escaped . 'n', '\\r', "g") let rs=substitute(rs, '\C' . s:re_escaped . 'R', '\\n', "g") endif if a:sort >= 2 let rs=substitute(rs, '\C' . s:re_escaped . '&', '\\R', "g") let rs=substitute(rs, '\C' . s:re_escaped . '\~', '\\N', "g") let rs=substitute(rs, '\C' . s:re_unescaped . '[&~]', '\\&', "g") let rs=substitute(rs, '\C' . s:re_escaped . 'R', '\&', "g") let rs=substitute(rs, '\C' . s:re_escaped . 'N', '\~', "g") endif return rs endfunction "End: s:ExchangeReplaceSpecials() "============================================================================= "============================================================================= "Import: macros/locrian.vim function! s:ReplaceAsStr(str, search, replacement, ...) let gsub = a:0 if a:0 > 0 let gsub = (a:1=~? 'g') ? 1 : 0 endif let oldstr = a:str let newstr = "" let len = strlen(a:search) let i = stridx(oldstr, a:search) while i >= 0 let newstr = newstr . strpart(oldstr, 0, i) . a:replacement let oldstr = strpart(oldstr, i + len) if gsub==0 break endif let i = stridx(oldstr, a:search) endwhile if strlen(oldstr)!=0 let newstr = newstr . oldstr endif return newstr endfunction "end s:ReplaceAsStr() "=============================================================================