On Mon, Jan 29, 2007 at 10:03:19AM -0700, Warren Michelsen wrote: > At 11:25 AM -0500 1/29/07, Ronald J Kimball sent email regarding Re: > Delete Table Column via grep: > >So, the first thing you need to know is that . matches any character except > >a newline. It sounds like your tags are on separate lines, so you need to > >allow . to match newlines as well. Use (?s) for this. The 's' is > >for single line; it treats the file like it's a single line, so newlines > >are just regular characters. That gives us this regex: > > (?s)<td.*</td>.*</tr> > > Is it possible, as an alternate strategy, to specify that between <td > and </tr> there may be multiple lines? Treating the entire line as > one long line seems to complicate things. Is there no way to specify > any character at all, including newlines?
Yes, if you just want to apply (?s) to part of the regex, you can do it like this: <td.*</td>(?s:.*)</tr> > So a '?' is the non-greedy specifier? Right, '?' makes a greedy quantifier into a non-greedy one. > >Unfortunately, in either case it's still the leftmost match. > >(?s)<td.*?</td>.*?</tr> finds the first <td in the file, then the first > ></td> after that, then the first </tr> after that. So if you've got > >multiple <td></td>s, it will match from the first <td> all the way through > >to the </tr>. That's not what we want either. > > Too bad there's no way to tell grep to work backwards from a found > point, i.e., find </tr> and select back to the first <td encountered. Well, you could start by reversing the contents of the file... (Actually, here's a paper about doing just that, in Perl: http://japhy.perlmonk.org/sexeger/sexeger.html) > >This regex should do what you want: > > > >(?s)<td(?:(?!</?td).)*</td>(?:(?!</?td).)*</tr> > > Worked just fine. The only drawback is that my Eudora turned various > characters of the pattern into sad smileys. Copied and pasted just > fine though. I always turn graphical smileys off in my IM client, just to avoid that problem. :) > Just out of curiosity, suppose I wanted to eliminate column N instead > of the last one. Is grep up to the task? (I'm certainly not.) Such > things as this would be nice to script: > Select a table, choose the "Delete Table Column" script from the > Scripts menu, respond with the number of the column to delete and > execute. Yes, you would want to match the appropriate number of columns before the target column. For example, if you wanted to remove the third column: Find (pretend it's all on one line) (?s)((?:<td(?:(?!</?td).)*</td>(?:(?!</?td).)*){2}) <td(?:(?!</?td).)*</td>((?:(?!</?td).)*</tr>) Replace \1\2 The first half matches exactly 2 columns; the second half is the same regex as before. If you were scripting it, you would ask for the number, subtract one, and then insert it where the 2 is in that regex. > If that can be done, then it ought to be possible to add a column as > well, at column position N, etc. Yes, you could do that with a very similar pattern; just move the part for the target column from the regex to the replacement: Find (?s)((?:<td(?:(?!</?td).)*</td>(?:(?!</?td).)*){2})((?:(?!</?td).)*</tr>) Replace \1<td></td> \2 You might need to tweak those patterns so that the whitespace comes out the way you like it. Ronald -- ------------------------------------------------------------------ Have a feature request? Not sure the software's working correctly? If so, please send mail to <[EMAIL PROTECTED]>, not to the list. List FAQ: <http://www.barebones.com/support/lists/bbedit_talk.shtml> List archives: <http://www.listsearch.com/BBEditTalk.lasso> To unsubscribe, send mail to: <[EMAIL PROTECTED]>
