我想搜索一系列数字(在VIM中),但不知道如何:
示例:
搜索数字< 10
- 所有数字必须包含小数值p.e. 9,20或8,532是小于10的值 - 可以使用或不使用千位分隔符插入(搜索)所有数字, 输出必须没有区别。
任何人都可以帮我一个代码示例,我该如何继续? 我已经尝试创建这样的东西,计算数字的位数,但它不能按我的意愿工作,因为这样我就不能将值搜索为> 90,50或< 200在飞行中。
答案 0 :(得分:1)
轻松你不能......但是通过努力,你可以做任何事情!
搜索数字> 450.20不是正则表达式的地方,但是:
h perl-patterns
:Vim没有实现(不幸的是)execution of arbitrary code in the regex: (?{perl code})
。
这意味着您必须使用一些替换(s
)或全局查找(g
)来将匹配作为数字进行评估,因此可以使用VimL轻松区分它。
但是你问一个/
命令。让我们用正则表达式来做。想法是匹配:
示例正则表达式可以占据一席之地。特别是因为我为每个模式重复了边界。
\%(\%([^ 0-9。] \ ZS \ | ^)[5-9] \ d \ d \%(\ d *)\ \%(\泽\ d \。?| $)\ | \%([^ 0-9。] \ ZS \ | ^)4 [6-9] \ d \%(\ d *)\ \%(\泽\ d \ |。?$)\ | \%([^ 0-9。] \ ZS \ | ^)45 [1-9] \%\ \%(\泽\ d \ | $)(\ d *)。?\ | \%([ ^ 0-9] \ ZS \ |。?^)\ d * \ d {4} \%(\ d *)\ \%(\泽\ 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
答案 1 :(得分:0)
我发现当我需要搜索比数字更大/更小的东西时,我还需要对匹配做一些事情。对于这种情况,submatch()
可能非常有用。
考虑我想将所有大于 132 且小于 500 的数字归零的情况。
搜索所有号码:/\v<[0-9.]+>
将 >132 和 <500 的所有数字归零::%s//\=submatch(0)>132 && submatch(0)<500 ? '0' : submatch(0)/g
如果您想逐行工作,也可以将这个技巧与 :global
一起使用:
标记数字 >132 和 <500 的行::%s//\=submatch(0)>132 && submatch(0)<500 ? 'deleteme' : submatch(0)/g
删除::g/deleteme/del
不幸的是,这不是找到它们的最佳解决方案!