Monday, August 12, 2013

Re: vim: how to use back reference to compare strings?

these are really cool , working , and good stuff to learn...
I'll need to take some time to learn from here...will consult you shortly with some questions..

thanks!



On Sun, Aug 11, 2013 at 3:52 AM, Benjamin R. Haskell <vim@benizi.com> wrote:
[Please bottom post, per the footer]


On Sat, 10 Aug 2013, ping song wrote:

I tested this again these test lines, doesn't work.

abc123 bla bla bla abc123 bla bla
abc123 bla bla bla abc1234 bla bla
abc123 bla bla bla abc123 bla bla
abc123 bla bla bla abc1234 bla bla
abc123 bla bla bla abc123 bla bla

:g#\(abc\d\+\)\(.*\)\(abc\d\+\)\(.*\)#s//\=Diff(submatch(1),submatch(2))/n

I got : "5 substitutions in 5 lines". no message got printed out...
any idea of what I missed here?

thanks anyway.

Try:

:g#\(abc\d\+\)\>.*\<\%(\1\>\)\@!\(abc\d\+\)#

Here's a diagram. (Not sure if I like it; trying this out):

   ┌──────────┬ an identifier
   │          ├ ending w/a word boundary
   │          │
   │          │ ┌ (don't need to capture)
   │          │ │ ┌ start of a word
   │          │ │ │ ┌ non-capturing (but needed for grouping)
   │          │ │ │ │
   │          │ │ │ │  ┌─────┬ 1st identifier we found
   │          │ │ │ │  │ ┌───┼ followed by a word boundary
   │          │ │ │ │  │ │   ├ doesn't match here
   │          │ │ │ │  │ │   │
   │          │ │ │ │  │ │   │  ┌ but there is *an* identifier
   │          │ │ │ │  │ │   │  │
   ├─────────┐├┐├┐├┐├─┐├┐├┐  ├─┐├─────────┐
:g#\(abc\d\+\)\>.*\<\%(\1\>\)\@!\(abc\d\+\)#

In English:

Find lines where:
  We capture an identifier.
  Match some stuff between.
  At a word boundary where the captured identifier doesn't match:
    There is some identifier.


Regular expressions have a bad tendency towards being "write-only".  I'm guessing the following code, if you're familiar with VimL, will be more maintainable, and probably easier to extend.  It also dumps everything in a quickfix list and opens the window if anything matches -- look at the lines with 'qf' on them if you don't like quickfix:

fun! FindDiffs()
  let i = 1
  let l = line('$')
  let buf = bufnr('.')
  let qf = []
  while i < l
    let m = matchlist(getline(i), '\(abc\d\+\).*\(abc\d\+\)')
    if len(m)
      let [a, b] = m[1:2]
      if a != b
        " when not using qf, echo it: echom a '!=' b 'on line' i
        call add(qf, {'bufnr': buf, 'lnum': i, 'text': a.' != '.b, 'type': 'W'})
      end
    end
    let i += 1
  endw
  call setqflist(qf) | cw
endf

--
Best,
Ben


--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
 
---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

No comments: