2008-12-15 7 views
2

En utilisant Ruby je suis en train de diviser le texte suivant avec un RegexRuby Regex match de moins échappé avec

~foo\~\=bar =cheese~monkey 

Où ~ ou = désigne le début du match de moins qu'il ne soit échappé avec \

Donc, il doit correspondre

~foo\~\=bar 

puis

=cheese 

puis

~monkey 

Je pensais que ce qui suit fonctionnerait, mais il ne fonctionne pas.

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

Quelle est une meilleure expression regex à utiliser?

modifier Pour être plus précis, l'expression rationnelle ci-dessus correspond à toutes les occurrences de = et ~

modifier solution de travail. Voici ce que j'ai trouvé pour résoudre le problème. J'ai trouvé que Ruby 1.8 a l'air en avant, mais n'a pas la fonctionnalité lookbehind. Donc, après avoir regardé un peu, je suis tombé sur this post dans comp.lang.ruby et compléta ce qui suit:

# 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 
+0

Pouvez-vous poster votre solution de travail? J'aimerais le voir. À votre santé! ;-) – Tomalak

Répondre

4

Que signifie « enlever la tête » signifie dans ce contexte?

Si vous souhaitez supprimer tout avant un certain char, cela va faire:

.*?(?<!\\)=  // 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) 

Remplacer par "", répéter, fait.

Si votre chaîne a exactement trois éléments ("1=2~3") et que vous voulez faire correspondre tous à la fois, vous pouvez utiliser:

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

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

Alternativement, vous divisez la chaîne en utilisant ce regex:

(?<!\\)[=~] 

returns: ['\~foo\~\=bar ', 'cheese', 'monkey'] for "\~foo\~\=bar =cheese~monkey" 
returns: ['', 'foo\~\=bar ', 'cheese', 'monkey'] for "~foo\~\=bar =cheese~monkey" 
+0

Il s'avère que regex dans la version de Ruby que j'utilise ne supporte pas lookbehind, mais j'ai été capable de l'utiliser pour le faire fonctionner. –

+0

La gemme Oniguruma et Ruby 1.9 feront des lookbehinds. –