views:

175

answers:

3

I'm trying to write a parser that uses two characters as token boundaries, but I can't figure out the regular expression that will allow me to ignore them when I'm regex-escaping the whole string.

Given a string like:

This | is || token || some ||| text

I would like to end up with:

This \| is || token || some \|\|\| text

where all of the | are escaped unless there are two of them together.

Is there a regular expression that will allow me to escape every | that isn't in a pair?

+2  A: 

No need regex. You are using Python after all. :)

>>> s="This | is || token || some ||| text"
>>> items=s.split()
>>> items
['This', '|', 'is', '||', 'token', '||', 'some', '|||', 'text']
>>> for n,i in enumerate(items):
...     if "|" in i and i.count("|")!=2:
...          items[n]=i.replace("|","\|")
...
>>> print ' '.join(items)
This \| is || token || some \|\|\| text
ghostdog74
A: 

Here's a way to do it with regular expressions in perl, if anyone's interested. I used two separate regular expressions, one for the single match and one for the 3 or more match. I'm sure it's possible to combine them, but regular expressions are already difficult enough to read without adding needless complexity.

#!/usr/bin/perl

#$s = "This | is || token || some ||| text";
$s = "| This |||| is || more | evil |";

$s =~ s/([^|]|^)(\|)([^|]|$)/\1\\\2\3/g;
$s =~ s{(\|{3,})}
{
   $a = $1;
   $a =~ s{\|} {\\\|}g;
   $a;
}eg;

print $s . "\n";

Outputs:

\| This \|\|\|\| is || more \| evil \|
inertial
+1  A: 

I don't see why you would need to regex-escape the tokens, but why not split up the string first and then escape them? This regex splits on two pipes that aren't preceded or followed by more pipes:

re.split('(?<!\|)\|\|(?!\|)', 'This | is || token || some ||| text')
>>> ['This | is ', ' token ', ' some ||| text']

By the way, there are testers for all of the more common regex flavors out there for the Googling. Here's one for Python: http://re.dabase.com/

Alan Moore