13

I am writing a paper with latex and accidentally wrote \cite[] instead of \cite{}. I could just go over the whole document by hand but I want to know how to do this in notepad++ using regexes.

I initially tried \\cite\[(.*)\] and replace with \cite{\1} which works for simple cases such as

\cite[hello world] blah blah 

However if there are two or more citations in a paragraph it matches all of them. So for example

\cite[aaa]\cite[bbb] something here \cite[ccc]

matches the whole line

How can I get a non greedy match so that the above line would be matched as 3 separate matches and the result of a replace command should give me

\cite{aaa}\cite{bbb} something here \cite{ccc}
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
twerdster
  • 4,977
  • 3
  • 40
  • 70
  • Better to use a more precise expression in the first place. Instead of using: `\[.*\]` or: `\[.*?\]`, it is more efficient to use: `\[[^[\]]*\]`. _Say what you mean, mean what you say!_ – ridgerunner Aug 24 '13 at 15:41

2 Answers2

34

Use a reluctant (aka non-greedy) expression:

\\cite\[(.*?)] 

See a live demo.

The addition of the question mark changes the .* from greedy (the default) to reluctant so it will consume as little as possible to find a match, ie it won't skip over multiple search terms matching start of one term all the way to the end of another term.

ie using .* the match would be

foo \cite[aaa]\cite[bbb] something here \cite[ccc] bar
    ^----------------------1---------------------^

but with .*? the matches would be:

foo \cite[aaa]\cite[bbb] something here \cite[ccc] bar
    ^---1----^^----------------2-----------------^

Minor note: ] does not need escaping.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • Unfortunately this doesnt work for me. I pasted the sample line I wrote in the question in notepad++ and then used your regex and it doesnt match anything. – twerdster Aug 24 '13 at 07:18
  • I've added a link showing the regex works. Maybe check it out and let me know what you think the problem you are having is. Be careful not to put any spaces at the end of the regex when you use it - I noticed when I copy-pasted it to test it that I picked up some trailing spaces which stopped it working properly. – Bohemian Aug 24 '13 at 07:27
  • @Bohemian I appreciate the effort. My question was aimed at notepad++ regex engine. Your regex does not work there. – twerdster Aug 24 '13 at 07:28
  • 4
    What version of Notepad++ are you using? It works for me in NPP v6.4.5. I'm searching for `\\cite\[(.*?)\]` and replacing it with `\\cite{\1}`. – Alan Moore Aug 24 '13 at 08:20
  • it wont seem to work for me in 7.7.1. Unless I'm missing something obvious...but regexp isn't a foreign concept to me and what I'm doing is fairly trivial so I can't imagine what I'd be missing...searching on the text `faa<>foo<>bar<>baz<>OK` for `<>.*?<>.*?<>OK` gives me the last 3 'tokens' instead of the last two 'tokens' – searchengine27 Jul 01 '21 at 22:21
  • @searchengine27 yes, because the first `<>` is matching between `faa` and `foo`. and `.*?` matches `foo<>bar`. As expected. What you *actually* want to match is not *anything* (ie a dot) but rather *not a `<`* ie `[^<]`, so `<>[^<]*?<>[^<]*?<>OK` but now do don't even need the question mark, so `<>[^<]*<>[^<]*<>OK` will do it. This is a common pattern often seen when matching delimited text, eg `"[^"]*"`. – Bohemian Jul 01 '21 at 23:08
  • well I thought using that example might make it more specific but you're right I've only forced it. The actual expression I was trying to test was actually `.*?<>.*?<>OK`, which also fails. – searchengine27 Jul 01 '21 at 23:44
1

Better to use a more precises expression in the first place:

\\cite\[([^[\]]*)\]

You must be using Notepad++ version 6 or higher (they upgraded to the PCRE regex engine at V6).

ridgerunner
  • 33,777
  • 5
  • 57
  • 69