title: Regex: Find groups of lowercase letters between HTML tag
body: <p>I'm attempting to develop a regular expression that can be run in <a href="http://code.google.com/p/sigil/" rel="nofollow noreferrer">Sigil</a>, the ePub 2 editor.</p>
  <p>Small-caps are a well-known problem within the current ePub reader ecosystem. Many readers, such as Adobe Digital Editions, do not support &quot;font-variant: small-caps&quot;. After trying several different workarounds, I've settled on creating fake small caps by transforming the text to uppercase and setting the previously lowercase letters to &quot;font-size: 0.75em&quot;.</p>
  <p>This process is extremely tedious, especially when working with books that have lots of endnotes with citations of other books.</p>
  <p>Say that I have a bunch of phrases in an HTML page tagged with an &quot;SC&quot; class. I've created a test phrase:</p>
  <pre><code>&lt;span class=&quot;SC&quot;&gt;Hello World! Testing: one tWo thrEE &amp;amp; W.T.F.&lt;/span&gt;
  &lt;span class=&quot;foo&quot;&gt;Don't touch me!&lt;/span&gt;
  </code></pre>
  <p>The goal is to write a regex that matches any lowercase letters within the &quot;SC&quot; span tag only, and replace them with:</p>
  <pre><code>&lt;span class=&quot;FSC&quot;&gt;LETTERS&lt;/span&gt;
  </code></pre>
  <p>I can manage to match and replace the letters in the first word &quot;Hello&quot;, but everything breaks down after that.</p>
  <p>Here's what I've got so far:</p>
  <p><strong>Find:</strong></p>
  <pre><code>(&lt;span class=&quot;SC&quot;&gt;.*?)([a-z]+)(.*&lt;/span&gt;)
  </code></pre>
  <p><strong>Replace:</strong></p>
  <pre><code>\1&lt;span class=&quot;FSC&quot;&gt;\U\2\E&lt;/span&gt;\3
  </code></pre>
  <p>The tricky part is then continuing to find the rest of the lowercase letters within that tag, now that a new &quot;FSC&quot; (Fake Small Caps) span tag has been introduced. Trying the same regex again results in &quot;span&quot; and then &quot;class&quot; getting the <em>FSC</em> treatment. Ideally, I'd like to be able to just keep hitting the &quot;Replace All&quot; button until no more matches are found.</p>
  <p>The above example would look like this when finished:</p>
  <pre><code>&lt;span class=&quot;SC&quot;&gt;H&lt;span class=&quot;FSC&quot;&gt;ELLO&lt;/span&gt; W&lt;span class=&quot;FSC&quot;&gt;ORLD&lt;/span&gt;! T&lt;span class=&quot;FSC&quot;&gt;ESTING&lt;/span&gt;: &lt;span class=&quot;FSC&quot;&gt;ONE&lt;/span&gt; &lt;span class=&quot;FSC&quot;&gt;T&lt;/span&gt;W&lt;span class=&quot;FSC&quot;&gt;O&lt;/span&gt; &lt;span class=&quot;FSC&quot;&gt;THR&lt;/span&gt;EE &amp;amp; W.T.F.&lt;/span&gt;
  &lt;span class=&quot;foo&quot;&gt;Don't touch me!&lt;/span&gt;
  </code></pre>
  <p>It's not pretty, but it works on every ePub reader that I've tested it on.</p>
  <p>If you google &quot;epub small caps regex&quot;, you'll come across a MobileRead wiki article that I edited to include this regex, which I've decided is not satisfactory:</p>
  <pre><code>(&lt;span class=&quot;[a-zA-Z0-9\- ]*?(?&lt;!F)SC[a-zA-Z0-9\-]*?&quot;&gt;(?:.+?&lt;span class=&quot;FSC&quot;&gt;.+?&lt;/span&gt;)*[\.|,|:|;|-|–|—|!|\?]? ?(?:&amp;amp;)? ?[A-Z]+)([a-z'’\. ]+)(.*?&lt;/span&gt;)
  </code></pre>
  <p>This ends up miniaturizing a bunch of punctuation and sometimes stops in the middle of a phrase. I started over, thinking there was probably a better solution that doesn't attempt to plan for every single possibility up front.</p>
  <p>If someone comes up with a better solution to this, you'll be the hero of the entire ePub publishing industry.</p>
  <h2>Update</h2>
  <p>I've added the accepted (and only) answer to the <a href="http://wiki.mobileread.com/wiki/EPubHacks" rel="nofollow noreferrer">Mobile Read wiki</a>. Please note that this regex has been altered specifically for use in Sigil; YMMV in other environments.</p>