Pequeñas delicias de las expresiones regulares
Posted: June 13th, 2009 | Author: FreedomCoder | Filed under: Open Source, Programming, how-to | Tags: Open Source, Programming, regexp, Ruby | No Comments »Como les conté acá y acá, estoy escribiendo un tokenizador para un wiki que estoy programando. Y hoy me encontré con una cosa muy extraña de las expresiones regulares.
En ruby la función match sirve para buscar el primer match de una regex dentro de un string. Por ejemplo (usando el irb):
irb(main):001:0> m = /a/.match "babab" => #<MatchData "a"> irb(main):002:0> m.pre_match => "b" irb(main):003:0> m[0] => "a"
En particular, el pre_match es lo que está antes del match en el string. También según había entendido (mal) /\Z/ matchea con el final del string. Por ejemplo:
irb(main):004:0> m = /\Z/.match "hola" => #<MatchData ""> irb(main):005:0> m.pre_match => "hola"
Pero, /\Z/ tiene un comportamiento muy extraño, aunque documentado, cuando el último caracter antes del final es un \n. Lo que pasa es que el pre_match queda ¡sin el\n del final!. Lo muestro en el irb:
irb(main):006:0> m = /\Z/.match "\n" => #<MatchData ""> irb(main):007:0> m.pre_match => ""Para que no se manduque el
\n, hay que usar/\z/(¡en minúscula!):
irb(main):008:0> m = /\z/.match "\n" => #<MatchData ""> irb(main):009:0> m.pre_match => "\n"Por lo tanto tuve que tocar el tokenizer, ahora la función de initialize quedó así (miren el cambio de la "Z" a "z"):
def initialize( delimiters ) @delimiter_list = [[/\z/, :finish]] + delimiters.to_a.map { |k,arr| arr.map { |re| [re, k] } }.inject([]) { |ac,ps| ac + ps } @match_cache = nil endY el test que captura el problema que genera usar \Z en vez de \z quedó así:
def test_carriage_return_ending tok = Tokenizer.new( :a_kind => [/!/] ) tok.source = "bang!\n" tok.next_token assert_equal true, tok.has_next? tok.next_token assert_equal true, tok.has_next? assert_equal "\n", tok.next_token[0].to_s assert_equal false, tok.has_next? endHappy hacking,
Aureliano.
(Via aurelianito.) Original Link: Pequeñas delicias de las expresiones regulares