Regex Help for Adding +14 to a Series
March 18, 2009 2:47 PM   Subscribe

I'm trying to use Regular Expressions in Textmate to do a Find/Replace. The goal: Find id="1", id="2", id="3", etc. and Replace with a value of +14, so that I replace yields id="15", id="16", id="17" etc. Thank you!

I don't mind doing the Finds/Replaces one at a time, so I'm not worried about greedy/reluctant, whatever. I just want a bit of an easier way to add +14 to a value.

So far I've been able to Find using id="*[0-9], but no luck for the Replace. Thanks mucho for any help!
posted by pinto to Computers & Internet (14 answers total)
You won't be able to do this with Textmate Find & Replace. You can find the numbers, but you can't do any math with them. I think you'll have to move to a Perl script or other scripting language to do this.
posted by pb at 3:21 PM on March 18, 2009

Response by poster: Thanks pb, i've found that I can do a normal find: id=" replace id="14+ and then use the Math bundle to evaluate and replace, but that's still a pain because I have to highlight the numbers. any other tips welcome!
posted by pinto at 3:24 PM on March 18, 2009

pb is right that you can't do math with regexps.

But risking stating the obvious (we all sometimes miss the obvious), you could do one search and replace for each number. The first would replace id="1" with id="15", etc. Whether this is practical depends on the meaning of "etc.".
posted by fritley at 3:26 PM on March 18, 2009

Response by poster: Yes, etc. goes into the hundreds, thanks though, Fritley.
posted by pinto at 3:28 PM on March 18, 2009

Yeah, TextMade regexes don't do /e so you can't eval an expression in the replace. Just hit the command like and do perl -pi -e 's/(?<=id=")(\d+)/$1+14/ge' filename.txt
posted by nicwolff at 3:38 PM on March 18, 2009 [2 favorites]

Best answer: Once you've replaced id=" with id="14+ couldn't you then use a regular expression to quickly highlight each of the instances of something that looks like 14+NNN and use the Math bundle? The regexp for that should be "\d+\+\d+". Once you set it up you would go Cmd-G, Ctrl-Shift-C, 2 -- over and over again until your whole document is done.

Of course a little perl or python script might be quicker if you have a lot of instances to replace.
posted by Emanuel at 3:38 PM on March 18, 2009

Best answer: Here's how I'd do it: find the IDs with id="(.+?)" and replace with id="((($1+14)))". Then do a search for \(\(\(.+?\)\)\) and keep hitting shift-ctrl-C-2 (evaluate and replace) then Cmd-G to move on to the next item, etc. That's 6 keypresses, so for hundreds of items probably good to record it as a macro.

On preview: Bah, Emanuel beat me to it. Anyway, that's how you could do what he describes.
posted by abcde at 3:48 PM on March 18, 2009

Response by poster: Metafilter wins again. Thanks to you's all.
posted by pinto at 3:56 PM on March 18, 2009

Oops, id="(\d+?)" would be better for my first one, obviously.
posted by abcde at 4:03 PM on March 18, 2009

If you're using emacs >= 22, you can embed code in your regexp, so you can do something like find id="\([^"]+\)", replace with id=\,(+ (string-to-integer \1) 14).

If you like TextMate, you'd probably enjoy emacs greatly...not as much eye candy, but most of the functionallity, plus lots more...
posted by james.nvc at 4:08 PM on March 18, 2009

Response by poster: Turns out this is the best Find string for to locate the 14+xx value without including quotation marks: 14\+\d+, then ctrl+shift+c, 2 does the calculation.
posted by pinto at 4:19 PM on March 18, 2009

Best answer: 1. Hit Command-Option R to invoke Filter Through Command...
2. Type:

perl -nle '@nf = split(/id="*[0-9]"/); $_ =~ m/id="*[0-9]"/g; $f1 = $&; @f = split (/"/,$f1); $v = $f[1]+10; print $nf[0]."id=\"".$v."\"".$nf[1]; '

3. Select Input: Document, and Output: Replace Document in the dialog box
4. Press Execute

I put in some regex to handle text before and after the id="...". There's probably a cleaner regex to do this, but this should get you started, I hope.
posted by Blazecock Pileon at 4:32 PM on March 18, 2009

Best answer: Replace the Perl in BP's step 2 with perl -pe 's/(?<=id=")(\d+)/$1+14/ge' for a cleaner solution within TextMate. BP, the (?<=...) is a zero-width look-behind assertion which means "match only after this", and the /e flag on the regex means "evaluate the replacement part".
posted by nicwolff at 8:03 PM on March 18, 2009 [1 favorite]

nicwolff's perl one-liner is much cleaner and nicer than my gobbledygook, I'd definitely use that with the Filter command.
posted by Blazecock Pileon at 9:52 PM on March 18, 2009

« Older What is nature's formulary?   |   Travel Filter: Ideas for last-minute vaca -... Newer »
This thread is closed to new comments.