views:

1298

answers:

1

Using Ruby I'm trying to split the following text with a Regex

~foo\~\=bar =cheese~monkey

Where ~ or = denotes the beginning of match unless it is escaped with \

So it should match

~foo\~\=bar

then

=cheese

then

~monkey

I thought the following would work, but it doesn't.

([~=]([^~=]|\\=|\\~)+)(.*)

What is a better regex expression to use?

edit To be more specific, the above regex matches all occurrences of = and ~

edit Working solution. Here is what I came up with to solve the issue. I found that Ruby 1.8 has look ahead, but doesn't have lookbehind functionality. So after looking around a bit, I came across this post in comp.lang.ruby and completed it with the following:

# Iterates through the answer clauses
def split_apart clauses
  reg = Regexp.new('.*?(?:[~=])(?!\\\\)', Regexp::MULTILINE)

  # need to use reverse since Ruby 1.8 has look ahead, but not look behind
  matches =  clauses.reverse.scan(reg).reverse.map {|clause| clause.strip.reverse}

  matches.each do |match|
    yield match
  end
end
+3  A: 

What does "remove the head" mean in this context?

If you want to remove everything before a certain char, this will do:

.*?(?<!\\)=      // anything up to the first "=" that is not preceded by "\"
.*?(?<!\\)~      // same, but for the squiggly "~"
.*?(?<!\\)(?=~)  // same, but excluding the separator itself (if you need that)

Replace by "", repeat, done.

If your string has exactly three elements ("1=2~3") and you want to match all of them at once, you can use:

^(.*?(?<!\\)(?:=))(.*?(?<!\\)(?:~))(.*)$

matches:  \~foo\~\=bar =cheese~monkey
         |      1      |   2  |  3   |

Alternatively, you split the string using this regex:

(?<!\\)[=~]

returns: ['\~foo\~\=bar ', 'cheese', 'monkey']   for "\~foo\~\=bar =cheese~monkey"
returns: ['', 'foo\~\=bar ', 'cheese', 'monkey'] for "~foo\~\=bar =cheese~monkey"
Tomalak
Turns out that regex in the version of Ruby I am using does not support lookbehind, but I was able to use this to get it to work.
Jamal Hansen
The Oniguruma gem and Ruby 1.9 will do lookbehinds.
Jamal Hansen