我想搜索一系列数字(在 VIM 中)但不知道如何:
示例:
- 搜索数字 > 450,20
- 搜索数字 > 1200(或 1.200)
- 搜索数字 > 10.000 AND < 1.000.000
搜索数字 < 10
--所有数字必须包含十进制值,例如9,20 或 8,532 是小于 10 的值
-- 所有数字都可以插入(搜索),带或不带千位分隔符, 输出一定没有差异。
任何人都可以帮我提供一个代码示例,我该如何继续?
我已经尝试创建类似的东西,计算位数,但它不能按我想要的方式工作,因为这样我就无法动态搜索 > 90,50 或 < 200 的值。
最佳答案
嗯,容易你不能......但是通过努力,你可以做任何事情!
搜索 > 450.20 的数字不是正则表达式的位置,而是:
h perl-patterns
:Vim 没有实现(不幸的是)执行正则表达式中的任意代码:(?{perl code})
。
这意味着您必须使用某种替换 (s
) 或全局查找 (g
) 来将匹配评估为数字,以便使用 VimL 轻松区分它。
但是您询问 /
命令。那么让我们用正则表达式来做吧。这个想法是匹配:
- x > 1000:\d\d\d\d(即 4 位数字)
- x > 500:[5-9]\d\d
- x > 460: 4[6-9]\d
- x > 450: 45[0-9]
- 冒号后面还有更多内容
示例正则表达式可以占据某个位置。特别是因为我为每个模式重复了单词边界。
\%(\%([^0-9.]\zs\|^)[5-9]\d\d\%(.\d*)\?\%(\ze\D\| $)\|\%([^0-9.]\zs\|^)4[6-9]\d\%(.\d*)\?\%(\ze\D\|$)\|\%([^0-9.]\zs\|^)45[1-9]\%(.\d*)\?\%(\ze\D\|$)\|\%([ ^0-9.]\zs\|^)\d*\d{4}\%(.\d*)\?\%(\ze\D\|$)\|\%([^0- 9.]\zs\|^)450.[3-9]\d*\|\%([^0-9.]\zs\|^)450.2[1-9]\d*\|\% ([^0-9.]\zs\|^)450.20\d*(\d\&[^0])\d*)
详细信息:
" Numbers >= 500 (looking like '***')
\%([^0-9.]\zs\|^\)[5-9]\d\d\%(\.\d*\)\?\%(\ze\D\|$\)
" Or numbers >= 460 (looking like '4**')
\|
\%([^0-9.]\zs\|^\)4[6-9]\d\%(\.\d*\)\?\%(\ze\D\|$\)
" Or numbers >= 451 (looking like '45*')
\|
\%([^0-9.]\zs\|^\)45[1-9]\%(\.\d*\)\?\%(\ze\D\|$\)
" Or numbers > 1000 (more than 4 digits)
\|
\%([^0-9.]\zs\|^\)\d*\d\{4}\%(\.\d*\)\?\%(\ze\D\|$\)
" Or numbers >= 450.3 (450.******)
\|
\%([^0-9.]\zs\|^\)450\.[3-9]\d*
" Or numbers >= 450.21 (450.2*****)
\|
\%([^0-9.]\zs\|^\)450\.2[1-9]\d*\)
" Or numbers > 450.20 (450.20 + 0.00000002000)
\|
\%([^0-9.]\zs\|^\)450\.20\d*\(\d\&[^0]\)\d*\)
我确实使用以下脚本做到了:
" Search for all numbers in a range
"
" Source me then (better put the last command defintion in your vimrc, then
"
" :Isearch > 450.20
" :Isearch > 1000 < 1000000
function! search#char_range(char, dir)
" Get string with range or '' if < 0 or > 9
if a:dir
let l:res = string( str2nr(a:char) + 1 )
if (l:res == 10) | return '' | endif
let l:res = '[' . l:res . '-9]'
else
let l:res = string( str2nr(a:char) - 1)
if (l:res == -1) | return '' | endif
let l:res = '[0-' . l:res . ']'
endif
return l:res
endfunction
function! search#isearch(num, dir, inc)
" Search any number supp to 9
"
" Number: (number) Limiting the range
" Direction: (boolean) Higher if true
" Inclusive: (boolean) Do the number is include >= or <=
"
let l:start_of_number = '\%([^0-9.]\zs\|^\)'
let l:pat_list = [l:start_of_number]
" Get hight and low
let l:list = split(a:num, '\.')
let l:high = l:list[0]
if (len(l:list) > 1)
let l:low = l:list[1]
else
let l:low = ''
endif
" 1/ High loop
" ~~~~~~~~~~~~
for l:c in split(l:high, '\zs')
" Get the higher range [-]
let l:range = search#char_range(l:c, a:dir)
if (l:range != '')
let l:pat = l:pat_list[0] . l:range
if (a:dir == 0 && l:pat_list[0] == l:start_of_number)
let l:pat .= '\?'
endif
call add(l:pat_list, l:pat)
else
if (a:dir)
break
else
let l:pat_list[-1] .= '\d\?'
endif
endif
" Add \d to previous guys
for i in range(1, len(l:pat_list) - 2)
let l:pat_list[i] .= '\d'
endfor
" Add to initial pattern
let l:pat_list[0] .= l:c
endfor
" 1.2/ Include with more digit
if a:dir
let l:biggest = l:start_of_number . '\d*\d\{' . string(len(l:pat_list)) . '}'
call add(l:pat_list, l:biggest)
endif
" 1.3/ indlude rest (after .)
for i in range(1, len(l:pat_list) - 1)
" The last digit is non optional (otherwise can match all)
if l:pat_list[i][-4:] == '\d\?'
let l:pat_list[i] = l:pat_list[i][:-3]
endif
let l:pat_list[i] .= '\%(\.\d*\)\?\%(\ze\D\|$\)'
endfor
" 2/ Low loop
" ~~~~~~~~~~~
if (len(l:low) != '')
let l:pat_list[0] .= '\.'
else
let l:pat_list[0] .= '\.\?'
endif
for l:c in split(l:low, '\zs')
" Get the higher range [-]
let l:cp1 = string( str2nr(l:c) + 1 )
if (l:cp1 == 10) | break | endif
call add(l:pat_list, l:pat_list[0] . '[' . cp1 . '-9]\d*')
" Add to initial pattern
let l:pat_list[0] .= l:c
endfor
" 2.2/ A very little drop
let l:pat = l:pat_list[0] . '\d*\(\d\&[^0]\)\d*'
call add(l:pat_list, l:pat)
" 3/ Add the number itself
if a:inc
let l:pat = join(l:pat_list, '\|')
else
let l:pat = join(l:pat_list[1:], '\|')
endif
return l:pat
endfunction
function! search#wrapper(...)
let l:pat = ''
for l:i in range(len(a:000))
" TODO check if there is a number after
if (a:000[l:i] == '>=')
if (l:pat != '') | let l:pat .= '\&' | endif
let l:pat .= '\%(' . search#isearch(a:000[l:i+1], 1, 1) . '\)'
elseif (a:000[l:i] == '>')
if (l:pat != '') | let l:pat .= '\&' | endif
let l:pat .= '\%(' . search#isearch(a:000[l:i+1], 1, 0) . '\)'
elseif (a:000[l:i] == '<=')
if (l:pat != '') | let l:pat .= '\&' | endif
let l:pat .= '\%(' . search#isearch(a:000[l:i+1], 0, 1) . '\)'
elseif (a:000[l:i] == '<')
if (l:pat != '') | let l:pat .= '\&' | endif
let l:pat .= '\%(' . search#isearch(a:000[l:i+1], 0, 0) . '\)'
endif
endfor
let @/ = l:pat
endfunction
command! -nargs=* Isearch call search#wrapper(<f-args>) | normal n
您可以在我的 github 上找到它(或更新的版本):https://github.com/tinmarino/Vimfiles/blob/master/autoload/search.vim
关于数字搜索范围(在搜索中使用实数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9905670/