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]>

Reply via email to