数字搜索范围(在搜索中使用实数)

标签 search vim numbers range

我想搜索一系列数字(在 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/

相关文章:

c - 如何确定特定节点是否找到所有其他节点?

jquery - 如何从YouTube搜索Jquery UI自动完成功能中获取单词列表?

macos - 使用 gvim 时窗口闪烁

Vim:复制/删除从第一个非空白字符到最后一个非空白字符的行

java - 如何仅使用 for 循环产生奇数

php - Elasticsearch - 希望在该特定字段可用或不可用的所有索引中按字段排序,如果不可用,则避免它

python - 使用 Tweepy 通过 API 1.1 搜索推文

vim - 使用 Vim 映射键

c - 数组的 For 循环 - 从以前的值添加

Java:将(长)对象转换为 double 的多种方法