Why does this regex result in four items?
<p>I want to split a string by <code></code>, <code>-&gt;</code>, <code>=&gt;</code>, or those wrapped with several spaces, meaning that I can get two items, <code>she</code> and <code>he</code>, from the following strings after being split:<br>
<code>"she he", "she  he", "she he ", "she  he  ", "she-&gt;he", "she  -&gt;he", "she=&gt;he", "she=&gt;  he", "  she-&gt;  he  ", "  she   =&gt;  he \n"</code></p>

<p>I have tried using this:</p>

<pre><code>re.compile("(?&lt;!^)((\\s*[-=]&gt;\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split(' she  -&gt; he \n')
</code></pre>

<p>What I get is a list with four items: <code>[' she', '  -&gt; ', '  -&gt; ', 'he \n']</code>.</p>

<p>And for this,  </p>

<pre><code>re.compile("(?&lt;!^)((\\s*[-=]&gt;\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split('she he')
</code></pre>

<p>I get this: <code>['she', ' ', None, 'he']</code>.</p>

<p>Why are there four items? And how can I get only two without the middle two?</p>

<p>As indicated in comments already, each pair of parentheses in your regex forms a capture group, and each of those is returned by the regex <code>split()</code> function.  As per the <a href="https://docs.python.org/2/library/re.html#re.split" rel="nofollow">documentation</a>,</p>

<blockquote>
  <p>If capturing parentheses are used in pattern, then the text of all groups in the pattern are also returned as part of the resulting list.</p>
</blockquote>

<p>Python regular expressions have a facility for non-capturing parentheses.  You use <code>(?:</code> instead of just <code>(</code> for the opening parenthesis to group without capturing.</p>

<pre><code>&gt;&gt;&gt; re.compile("(?&lt;!^)((\\s*[-=]&gt;\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split('she he')
['she', ' ', None, 'he']
&gt;&gt;&gt; re.compile("(?&lt;!^)(?:(?:\\s*[-=]&gt;\\s*)|[\\s+\t])(?!$\n)(?=[^\s])").split('she he')
['she', 'he']
</code></pre>

<p>It's not exactly clear why you include a tab explicitly in the character class with <code>\s</code>; the <code>\s</code> already includes tab as one of the many whitespace characters it matches.</p>

<p>It's also not clear what you expect <code>$\n</code> to match.  <code>$</code> is the end of the line and <code>\n</code> is a literal newline character, so you seem to be trying to deal with newlines; but <code>$</code> alone already covers that.  The only difference between <code>$</code> and <code>$\n</code> is that if the end of the string (the last line in a multi-line string) is not newline-terminated, that will not match the latter.</p>

<p>The <code>(?&lt;!^)</code> is also peculiar -- a better way to avoid matching an empty string is to make sure your regular expression always matches something.</p>

<p>From your requirements, it seems that</p>

<pre><code>re.compile(r'\s*[-=]&gt;\s*|\s+').split('he she')
</code></pre>

<p>would do what you want more succinctly and readably.  This matches an ASCII arrow (single- or double-stoke) with optional whitespace on both sides, or if that fails, falls back to a sequence of whitespace.</p>

python regex split