<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>RegEx &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/tag/regex/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Wed, 17 Sep 2025 19:12:04 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>RegEx Examples: 10 Practical Patterns You Can Copy and Paste</title>
		<link>https://blog.xojo.com/2025/09/18/regex-examples-10-practical-patterns-you-can-copy-and-paste/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Thu, 18 Sep 2025 11:00:00 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Code Snippets]]></category>
		<category><![CDATA[Data Extraction]]></category>
		<category><![CDATA[RegEx]]></category>
		<category><![CDATA[Text Processing]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=15351</guid>

					<description><![CDATA[Looking for RegEx examples you can drop straight into your project? This practical cheat sheet focuses on the most searched tasks, such as find/replace, extracting&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Looking for RegEx examples you can drop straight into your project? This practical cheat sheet focuses on the most searched tasks, such as find/replace, extracting values, lookahead/lookbehind, and non-greedy matches, using Xojo’s RegEx class with concise, ready-to-run snippets. Copy, paste, ship.</p>



<h2 class="wp-block-heading" id="setup-3-lines-you’ll-reuse">Setup (3 lines you’ll reuse)</h2>



<pre class="wp-block-code"><code>Var re As New RegEx
Var opt As New RegExOptions
re.Options = opt</code></pre>



<h2 class="wp-block-heading" id="replace-all-occurrences-word-boundary">1) Replace all occurrences (word boundary)</h2>



<p>Goal: a → the (whole word)</p>



<pre class="wp-block-code"><code>Var re As New RegEx
Var opt As New RegExOptions
opt.ReplaceAllMatches = True
re.Options = opt

re.SearchPattern = "\ba\b"
re.ReplacementPattern = "the"
MessageBox(re.Replace("a bus on a street in a town"))
' the bus on the street in the town</code></pre>



<h2 class="wp-block-heading" id="strip-html-tags">2) Strip HTML tags</h2>



<pre class="wp-block-code"><code>Var re As New RegEx
Var opt As New RegExOptions
opt.ReplaceAllMatches = True
re.Options = opt

re.SearchPattern = "&lt;&#91;^&lt;>]+>"
re.ReplacementPattern = ""
MessageBox(re.Replace("&lt;p>Hello &lt;b>world&lt;/b>.&lt;/p>"))
' Hello world.</code></pre>



<h2 class="wp-block-heading" id="extract-the-first-number-capture-groups">3) Extract the first number (capture groups)</h2>



<pre class="wp-block-code"><code>re.SearchPattern = "(\d+)"
Var m As RegExMatch = re.Search("Order #12345 shipped")
If m &lt;> Nil Then MessageBox(m.SubExpressionString(1)) ' 12345</code></pre>



<h2 class="wp-block-heading" id="reformat-dates-with-1-2-3">4) Reformat dates with $1, $2, $3</h2>



<p>Goal: YYYY-MM-DD → DD/MM/YYYY</p>



<pre class="wp-block-code"><code>Var re As New RegEx
Var opt As New RegExOptions
opt.ReplaceAllMatches = True
re.Options = opt

re.SearchPattern = "(\d{4})-(\d{2})-(\d{2})"
re.ReplacementPattern = "$3/$2/$1"
MessageBox(re.Replace("Due: 2025-09-09 and 2025-12-31"))
' Due: 09/09/2025 and 31/12/2025</code></pre>



<h2 class="wp-block-heading" id="find-all-words-simple-iterator">5) Find all words (simple iterator)</h2>



<pre class="wp-block-code"><code>re.SearchPattern = "\w+"
Var match As RegExMatch = re.Search("one two three")
While match &lt;> Nil
  System.DebugLog(match.SubExpressionString(0))
  match = re.Search ' continues from last position
Wend</code></pre>



<h2 class="wp-block-heading" id="replace-only-the-second-occurrence">6) Replace only the second occurrence</h2>



<pre class="wp-block-code"><code>Var s As String = "a bus drove on a street in a town"
re.SearchPattern = "\ba\b"
re.ReplacementPattern = "the"

Var first As RegExMatch = re.Search(s) ' find first
If first &lt;> Nil Then
  s = re.Replace ' replaces the next match only
End If

MessageBox(s)
' a bus drove on the street in a town</code></pre>



<h2 class="wp-block-heading" id="lookarounds">7) Lookarounds</h2>



<p>Match “foo” not followed by “bar”</p>



<pre class="wp-block-code"><code>re.SearchPattern = "foo(?!bar)"</code></pre>



<h3 class="wp-block-heading" id="negative-lookahead-match-only-http-not-https-urls">7.1 Negative lookahead: match only http (not https) URLs</h3>



<pre class="wp-block-code"><code>Var re As New RegEx
re.SearchPattern = "http(?!s)://\S+" ' http:// not followed by s
Var txt As String = "http://a.com and https://b.com"
Var m As RegExMatch = re.Search(txt)
While m &lt;> Nil
  System.DebugLog(m.SubExpressionString(0)) ' http://a.com
  m = re.Search
Wend</code></pre>



<h3 class="wp-block-heading" id="positive-lookbehind--optional-decimals-amounts-right-after-">7.2 Positive lookbehind + optional decimals: amounts right after $</h3>



<pre class="wp-block-code"><code>Var re As New RegEx
re.SearchPattern = "(?&lt;=\$)\d+(?:\.\d{2})?" ' $123 or $123.45 → capture just the number
Var txt As String = "Total: $19.99, Tax: $2"
Var m As RegExMatch = re.Search(txt)
While m &lt;> Nil
  System.DebugLog(m.SubExpressionString(0)) ' 19.99, 2
  m = re.Search
Wend</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Tip:</p>



<ul class="wp-block-list">
<li>Fixed‑width only for look‑behind: avoid quantifiers like +, * inside (?&lt;=…)/(?&lt;!…).</li>



<li>Use lookarounds when you need context to the left/right but don’t want it included in the match or replacement.</li>
</ul>
</blockquote>



<h2 class="wp-block-heading" id="smallest-span-between-tags-non‑greedy">8) Smallest span between tags (non‑greedy)</h2>



<pre class="wp-block-code"><code>re.SearchPattern = "&lt;b>.+?&lt;/b>" ' or: opt.Greedy = False</code></pre>



<h2 class="wp-block-heading" id="extract-emails-simple-demo">9) Extract emails (simple demo)</h2>



<pre class="wp-block-code"><code>re.SearchPattern = "&#91;A-Za-z0-9._%+-]+@&#91;A-Za-z0-9.-]+\.&#91;A-Za-z]{2,}"
Var em As RegExMatch = re.Search("Contact: me@example.com")
If em &lt;> Nil Then MessageBox(em.SubExpressionString(0)) ' me@example.com</code></pre>



<h2 class="wp-block-heading" id="start-at-character-position-n-utf‑8-safe">10) Start at character position N (UTF‑8 safe)</h2>



<pre class="wp-block-code"><code>Var t As String = "ąβç sample"
Var charPos As Integer = 5 ' 1-based character index
re.SearchPattern = "\w+"
re.SearchStartPosition = t.Left(charPos - 1).Bytes ' convert char index → byte offset
Var mm As RegExMatch = re.Search(t)
If mm &lt;> Nil Then System.DebugLog(mm.SubExpressionString(0))</code></pre>



<h2 class="wp-block-heading" id="quick-replacement-references">Quick replacement references</h2>



<ul class="wp-block-list">
<li><strong>$&amp;</strong>&nbsp;= entire match (This reference represents the&nbsp;<em>exact</em>&nbsp;piece of text that your regular expression found. It’s incredibly useful if you want to add something before or after the matched text without changing the match itself.)</li>



<li><strong>$1…$50</strong>&nbsp;= captured groups (Regular expressions allow you to define specific “groups” within your match by enclosing parts of your pattern in parentheses&nbsp;<code>()</code>. Each set of parentheses creates a captured group.)</li>



<li><strong>$`</strong>&nbsp;= text before the match (This special reference represents&nbsp;<em>all</em>&nbsp;the text in your original string that appears&nbsp;<em>before</em>&nbsp;the part your regular expression matched. It’s handy if you want to keep the beginning of the string intact while making a change in the middle.)</li>



<li><strong>$’</strong>&nbsp;= text after the match (This refers to&nbsp;<em>all</em>&nbsp;the text in your original string that comes&nbsp;<em>after</em>&nbsp;the current match. It’s useful for preserving the end of the string.)</li>
</ul>



<h2 class="wp-block-heading" id="options-you’ll-use-most">Options you’ll use most</h2>



<pre class="wp-block-code"><code>opt.ReplaceAllMatches = True  ' global replace
opt.CaseSensitive = True      ' default is False
opt.DotMatchAll = True        ' make . match newlines
opt.Greedy = False            ' prefer shortest matches
opt.TreatTargetAsOneLine = True ' ^ and $ match whole string</code></pre>



<h2 class="wp-block-heading" id="common-gotchas">Common gotchas</h2>



<ul class="wp-block-list">
<li>Greediness: “.+” can overmatch; use .+? or set Greedy = False.</li>



<li>Case sensitivity: default searches are case‑insensitive; enable CaseSensitive when exact case matters.</li>



<li>UTF‑8: SearchStartPosition is byte‑based; convert character index to bytes (see example ↑).</li>



<li>Lookbehind must be fixed‑width.</li>



<li>Iteration: After the first Search(targetString), call re.Search with no args to continue.</li>
</ul>



<h2 class="wp-block-heading" id="wrap‑up">Wrap‑up</h2>



<p>Got a tricky pattern, validation, parsing, or a lookaround edge case you want covered? Drop a comment in the forums with your use.</p>



<p>Happy matching!</p>



<p><em>Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>2020 Xojo Design Award Winners</title>
		<link>https://blog.xojo.com/2020/03/13/2020-xojo-design-award-winners/</link>
		
		<dc:creator><![CDATA[Alyssa Foley]]></dc:creator>
		<pubDate>Fri, 13 Mar 2020 16:36:44 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[XDC]]></category>
		<category><![CDATA[XOJO.CONNECT]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Design Awards]]></category>
		<category><![CDATA[Monkeybread Software]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[RegEx]]></category>
		<category><![CDATA[Vertical Market]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=6748</guid>

					<description><![CDATA[Today we are pleased to announce the winners of the 2020 Xojo Design Awards. Judging is never an easy job, but this year the submissions were such a diverse range of apps we found it both exciting and difficult! The Design Awards honor excellence in software design. These awards are a great opportunity to learn about some of the best apps made with Xojo. Support Xojo and the Xojo community by sharing and congratulating these winners!]]></description>
										<content:encoded><![CDATA[
<p>Today we are pleased to announce the winners of the 2020&nbsp;<a href="https://www.xojo.com/designawards/">Xojo Design Awards</a>. Judging is never an easy job, but this year the submissions were such a diverse range of apps we found it both exciting and difficult! The Design Awards honor excellence in software design in the following categories: Best Consumer App, Best iOS App, Best Lifestyle App, Best Developer Tool, Best Vertical Market Apps and Best Plugin. These awards are a great opportunity to learn about some of the best apps made with Xojo. Support Xojo and the Xojo community by sharing and congratulating these winners!</p>



<h3 class="wp-block-heading">The 2020 Xojo Design Award Winners are:</h3>



<h4 class="wp-block-heading">Best Consumer App &#8211; HDRtist NX</h4>



<p><a href="https://www.ohanaware.com">Ohanaware</a>: A detail-oriented High Dynamic Range Imaging app for MacOS X.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img fetchpriority="high" decoding="async" width="1024" height="510" src="https://blog.xojo.com/wp-content/uploads/2020/03/hdrtist-1024x510.png" alt="" class="wp-image-6755" srcset="https://blog.xojo.com/wp-content/uploads/2020/03/hdrtist-1024x510.png 1024w, https://blog.xojo.com/wp-content/uploads/2020/03/hdrtist-300x149.png 300w, https://blog.xojo.com/wp-content/uploads/2020/03/hdrtist-768x382.png 768w, https://blog.xojo.com/wp-content/uploads/2020/03/hdrtist-1536x765.png 1536w, https://blog.xojo.com/wp-content/uploads/2020/03/hdrtist.png 2040w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></div>



<h4 class="wp-block-heading">Best iOS App &#8211; PropertyMe Manager</h4>



<p><a href="https://apps.apple.com/au/app/propertyme-manager/id936934755">PropertyMe</a>: The PropertyMe Manager app gives property managers access to their portfolio wherever they are.</p>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><img decoding="async" src="https://blog.xojo.com/wp-content/uploads/2020/03/propertyme.gif" alt="" class="wp-image-6756" width="234" height="506"/></figure></div>



<h4 class="wp-block-heading">Best Lifestyle App &#8211; Crossword Wizard</h4>



<p><a href="https://www.crosswordwizard.com.au">Rush Software</a>: Create and play crossword games.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img decoding="async" width="719" height="507" src="https://blog.xojo.com/wp-content/uploads/2020/03/crosswordwizard.jpg" alt="" class="wp-image-6758" srcset="https://blog.xojo.com/wp-content/uploads/2020/03/crosswordwizard.jpg 719w, https://blog.xojo.com/wp-content/uploads/2020/03/crosswordwizard-300x212.jpg 300w" sizes="(max-width: 719px) 100vw, 719px" /></figure></div>



<h4 class="wp-block-heading">Best Developer Tool &#8211; RegExRX</h4>



<p><a href="http://www.mactechnologies.com">MacTechnologies Consulting</a>: A cross-platform Regular Expression development tool.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="788" height="768" src="https://blog.xojo.com/wp-content/uploads/2020/03/MicrosoftTeams-image-1.png" alt="" class="wp-image-6766" srcset="https://blog.xojo.com/wp-content/uploads/2020/03/MicrosoftTeams-image-1.png 788w, https://blog.xojo.com/wp-content/uploads/2020/03/MicrosoftTeams-image-1-300x292.png 300w, https://blog.xojo.com/wp-content/uploads/2020/03/MicrosoftTeams-image-1-768x749.png 768w" sizes="auto, (max-width: 788px) 100vw, 788px" /></figure></div>



<h4 class="wp-block-heading">Best Vertical Market App &#8211; qwireCast</h4>



<p><a href="http://www.qwirecast.com">qWire</a>: Desktop app to help Hollywood casting director make cast lists.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="786" height="768" src="https://blog.xojo.com/wp-content/uploads/2020/03/MicrosoftTeams-image-2.png" alt="" class="wp-image-6769" srcset="https://blog.xojo.com/wp-content/uploads/2020/03/MicrosoftTeams-image-2.png 786w, https://blog.xojo.com/wp-content/uploads/2020/03/MicrosoftTeams-image-2-300x293.png 300w, https://blog.xojo.com/wp-content/uploads/2020/03/MicrosoftTeams-image-2-768x750.png 768w" sizes="auto, (max-width: 786px) 100vw, 786px" /></figure></div>



<h4 class="wp-block-heading">Best Vertical Market App &#8211; bMD Medical Software*</h4>



<p><a href="https://historiasclinicas.com.ar">bMD biomedical Developments SRL</a>: Medical practice management software.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="888" height="550" src="https://blog.xojo.com/wp-content/uploads/2020/03/MicrosoftTeams-image.png" alt="" class="wp-image-6762" srcset="https://blog.xojo.com/wp-content/uploads/2020/03/MicrosoftTeams-image.png 888w, https://blog.xojo.com/wp-content/uploads/2020/03/MicrosoftTeams-image-300x186.png 300w, https://blog.xojo.com/wp-content/uploads/2020/03/MicrosoftTeams-image-768x476.png 768w" sizes="auto, (max-width: 888px) 100vw, 888px" /></figure></div>



<h4 class="wp-block-heading">Best Plugin &#8211; MBS Plugins</h4>



<p><a href="https://www.monkeybreadsoftware.de/xojo/">MonkeyBread Software</a>: This huge toolbox for Xojo developers includes thousands of classes, controls and examples to extend Xojo.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="750" height="788" src="https://blog.xojo.com/wp-content/uploads/2020/03/monkeybreadplugin.jpg" alt="" class="wp-image-6761" srcset="https://blog.xojo.com/wp-content/uploads/2020/03/monkeybreadplugin.jpg 750w, https://blog.xojo.com/wp-content/uploads/2020/03/monkeybreadplugin-286x300.jpg 286w" sizes="auto, (max-width: 750px) 100vw, 750px" /></figure></div>



<p>*Yes, there are two Best Vertical Market Apps, they were both so good we had no choice but to award them both!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Adventures in Regular Expressions</title>
		<link>https://blog.xojo.com/2018/10/22/adventures-in-regular-expressions/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Mon, 22 Oct 2018 16:19:27 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[RegEx]]></category>
		<category><![CDATA[Regular Expression]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5041</guid>

					<description><![CDATA[Normally I'd crack my knuckles and start on a Xojo project and use string find/replacing to massage the text. But this is messy and tedious.

So I thought, why not try Regular Expressions (RegEx)? I don't really know much about RegEx and frankly they scare me a bit.]]></description>
										<content:encoded><![CDATA[<p>As you probably know, every version of Xojo includes an extensive list of release notes that is included in the Documentation folder as an HTML file called ReleaseNotes.htm.</p>
<p>To make these even easier to access, I needed a way to get these into the wiki. It would be easiest if I could just copy and paste the HTML contents onto a wiki page, but MediaWiki can&#8217;t quite process all the HTML in that file so I needed a way to clean it up a bit.</p>
<p><span id="more-5041"></span></p>
<p>Take a look at a single line that contains a release note:</p>
<pre>&lt;tr class="spacer"&gt;&lt;td class="reportid"&gt;&lt;a href="feedback://showreport?report_id=52522"&gt;52522&lt;/a&gt;&lt;/td&gt;&lt;td class="category"&gt;Framework » All&lt;/td&gt;&lt;td class="desc"&gt;Added AntiAliasMode property on Graphics class. This property controls the level of interpolation/quality when drawing scaled Pictures. Valid modes are from the Graphics.AntiAliasModes enumeration: LowQuality, DefaultQuality, and HighQuality. The default is DefaultQuality.&lt;/td&gt;&lt;/tr&gt;</pre>
<p>This is a row in an HTML table. The problem is the &lt;a href&gt; part which MediaWiki does not use for displaying links. So I needed a way to clean that up. There are also some &lt;tbody&gt; tags that I needed to remove.</p>
<p>Normally I&#8217;d crack my knuckles and start on a Xojo project and use string find/replacing to massage the text. But this is messy and tedious.</p>
<p>So I thought, why not try Regular Expressions (RegEx)? I don&#8217;t really know much about RegEx and frankly they scare me a bit. After all, who can make heads or tails of something that looks like this:</p>
<pre>\b(\d{1,2})([/-])(\d{1,2})\2(\d{4}|\d{2})\b</pre>
<p>That gibberish above is called a RegEx pattern and apparently that one is for date validation.</p>
<p>Anyway, I figured I would give RegEx a try. My first challenge was to find a pattern that I could start with and maybe modify. Heading to the Xojo doc pages for the <a href="https://docsupgrade.xojo.com/RegEx">RegEx class</a>, I found this pattern to remove HTML tags from text on the <a href="https://docsupgrade.xojo.com/RegEx.Replace">RegEx.Replace</a> page&#8217;s Sample Code:</p>
<pre>&lt;[^&lt;&gt;]+&gt;</pre>
<p>Since I did need to remove HTML tags, I figured it was a good place to start.</p>
<p>To explain this pattern:</p>
<ol>
<li>The &#8220;&lt;&#8221; is the starting character</li>
<li>The &#8220;[&#8221; bracket starts a character class</li>
<li>The &#8220;^&#8221; means not, so &#8220;^&lt;&gt;&#8221; means all characters except &#8220;&lt;&#8221; and &#8220;&gt;&#8221;</li>
<li>The &#8220;]&#8221; ends the character class and the &#8220;+&#8221; means match 1 or more characters</li>
<li>End with a &#8220;&gt;&#8221; character</li>
</ol>
<p>So that means match all the text that starts with a &#8220;&lt;&#8221; has one or more characters after that except &#8220;&lt;&#8221; and &#8220;&gt;&#8221; and ends with a &#8220;&gt;&#8221;.</p>
<p><em>FYI: For all my RegEx testing I used <a href="https://itunes.apple.com/us/app/regexrx/id498370702?mt=12">RegExRX</a> &#8212; an excellent tool for dealing with RegEx written in Xojo by long-time Xojo developer Kem Tekinay.</em></p>
<p>After starting RegExRX I put the above pattern in the Search Pattern field and pasted a small snippet of the HTML into the Source Text field. I could immediately see that all the HTML tags were matched.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5043" src="https://blog.xojo.com/wp-content/uploads/2018/10/2018-10-12_09-54-33.png" alt="" width="735" height="692" /></p>
<p>But I did not need all the HTML tags to be matched, I only needed &lt;a&gt; and &lt;tbody&gt;. A slight modification to the above pattern can tell it to only find text that starts with &#8220;&lt;a&#8221; or &#8220;&lt;/a&#8221;. Looking at the RegEx reference on the <a href="https://docsupgrade.xojo.com/RegEx">RegEx page</a> I saw that the &#8220;?&#8221; character means 0 or 1 matches. So I can change the pattern to this:</p>
<pre>&lt;/?a[^&lt;&gt;]*&gt;</pre>
<p>Which means find HTML tags that start with &#8220;&lt;a&#8221; or &#8220;&lt;/a&#8221;. With this pattern I can see that only the &lt;a&gt; and &lt;/a&gt; tags are highlighted:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5055" src="https://blog.xojo.com/wp-content/uploads/2018/10/2018-10-12_13-24-33.png" alt="" width="735" height="851" /></p>
<p>To actually remove the tags I use a Replacement and replace an empty string for the matched tag. Switching to the Replace tab in RegExRX, this is what that looks like:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5056" src="https://blog.xojo.com/wp-content/uploads/2018/10/2018-10-12_13-28-45.png" alt="" width="735" height="851" /></p>
<p>To do the same things for &lt;tbody&gt; I changed the pattern to this:</p>
<pre>&lt;/?tbody[^&lt;&gt;]*&gt;</pre>
<p>Now it was time to use this in a Xojo project. You use the <a href="https://docsupgrade.xojo.com/RegEx">RegEx class</a> to work with regular expressions. This function takes text (loaded from a release notes file) and applies the search pattern and an empty replace pattern to remove the tags and stick the result into the Clipboard so I can paste it into the wiki:</p>
<pre>Private Function CleanHTML(html As String) as String
  Dim re As New RegEx
  re.SearchPattern = "&lt;/?a[^&lt;&gt;]*&gt;" // Find &lt;a href&gt;&lt;/a&gt; tags for removal
  re.ReplacementPattern = ""
  re.Options.ReplaceAllMatches = True
  Dim plainHTML As String = re.Replace(html)

  // Remove any &lt;tbody&gt; tags as MediaWiki doesn't process them
  re.SearchPattern = "&lt;/?tbody[^&lt;&gt;]*&gt;"
  re.ReplacementPattern = ""
  re.Options.ReplaceAllMatches = True
  plainHTML = re.Replace(plainHTML)

  Dim c As New Clipboard
  c.Text = plainHTML

  Return plainHTML
End Function</pre>
<p>This worked wonderfully, but after trying this out I decided I wanted to keep the links to the Feedback case around so that you can click on a case number to open the case in the Feedback app and read all its history. This means that instead of removing the &lt;a&gt; tags I needed to change them from this:</p>
<pre>&lt;a href="feedback://showreport?report_id=52522"&gt;52522&lt;/a&gt;</pre>
<p>to this:</p>
<pre>[http://feedback.xojo.com/case/52522 52522]</pre>
<p>To do this I now needed to use a subgroup to save the case ID so I could use it as part of the replacement string. To create subgroups you group parts of the RegEx pattern using parentheses. Essentially I wanted to have clear parts of the pattern for the &lt;a&gt; start tag, the value (case ID) and the &lt;/a&gt; closing tag.</p>
<p>I started by simplifying the &lt;a&gt; tag search to this to just match the opening tag:</p>
<pre>&lt;a[^&lt;&gt;]*&gt;</pre>
<p>I then added a part to match the case ID which is just a series of 1 or more numbers. RegEx has a command to match only digits, which is &#8220;\d&#8221;, to which we can add the &#8220;+&#8221; to to repeat it one or more times as needed. I then wrapped that in parentheses to get a group resulting in this:</p>
<pre>&lt;a[^&lt;&gt;]*&gt;(\d+)</pre>
<p>Lastly I added the part to match the closing tag &lt;/a&gt; to get the final pattern:</p>
<pre>&lt;a[^&lt;&gt;]*&gt;(\d+)&lt;/a&gt;</pre>
<p>In the end you can see the &lt;a&gt;, &lt;/a&gt; tags and the case ID value are all matched:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5057" src="https://blog.xojo.com/wp-content/uploads/2018/10/2018-10-12_13-32-42.png" alt="" width="735" height="851" /></p>
<p>This changed pattern means I now have a group I can use for the replacement. Switching to the Replace tab in RegExRX you&#8217;ll notice that the entire matched text is removed because the Replace Pattern is blank. Typing &#8220;$1&#8221; (this contains the group with the Case ID value) in the Replace Pattern showed the Case ID in the replaced text:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5058" src="https://blog.xojo.com/wp-content/uploads/2018/10/2018-10-12_13-33-30.png" alt="" width="735" height="851" /></p>
<p>And now I put the rest of the text I wanted for the Replace Pattern:</p>
<pre>[feedback://showreport?report_id=$1 $1]</pre>
<p>The replaced text now looks like what I wanted:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-5059" src="https://blog.xojo.com/wp-content/uploads/2018/10/2018-10-12_13-34-06.png" alt="" width="735" height="851" /></p>
<p>Here is the updated Xojo function:</p>
<pre>Private Function CleanHTML(html As String) as String
  Dim re As New RegEx
  re.SearchPattern = "&lt;a[^&lt;&gt;]*&gt;(\d+)&lt;/a&gt;" // Find &lt;a href&gt; tags and save case # as a group
  re.ReplacementPattern = "[http://feedback.xojo.com/case/$1 $1]" // Swap in wiki link format with correct URL
  re.Options.ReplaceAllMatches = True
  Dim plainHTML As String = re.Replace(html)

  // Remove any &lt;tbody&gt; tags as MediaWiki doesn't process them
  re.SearchPattern = "&lt;/?tbody[^&lt;&gt;]*&gt;"
  re.ReplacementPattern = ""
  re.Options.ReplaceAllMatches = True
  plainHTML = re.Replace(plainHTML)

  Dim c As New Clipboard
  c.Text = plainHTML

  Return plainHTML
End Function</pre>
<p>I hope this little adventure in RegEx has helped you appreciate how wonderful they are for string searching and replacement. I&#8217;m still no expert, but I found this to be much, much better than messy string searching and parsing using InStr and friends.</p>
<p>To learn more about Regular Expressions, check out the <a href="https://regexone.com">RegExOne site</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
