[ruby-it] Confronto usando regexp

gabriele renzi surrender_it a yahoo.it
Lun 16 Mar 2009 18:03:15 CET





> From: Stefano De nigris <stedenigris a hotmail.com>
> To: ml a lists.ruby-it.org
> Sent: Friday, 13 March, 2009 13:45:42
> Subject: Re: [ruby-it] Confronto usando regexp
> 

> L'ho assegnato cosi:
> if /:#{$record};/ =~ elementi1
> var=elementi1.index ":"
> $varrecord=elementi1[0..var-1]
> end

questo puoi farlo più facilmente usando i capturing group, ovvero usando la regex per memorizzare il valore

record_name= "nome.*"
rgx = /:(#{record_name});/
elements = ":nome foo bar;"
# il gruppo 1 sarà la cosa che matcha tra le parentesi tonde
if m=rgx.match(elements)
 record= m[1]
end

p record #=> "nome foo bar"

Occhio che non ho usato variabili globali, perché non servono quelle locali sono sufficienti come ti dicevano prima.


> Beh allora ti dico il mio problema...io ho creato un programma che deve 
> convertire le istruzioni da delphi in ruby.

bravo sembra un bel progetto, io ne avevo fatto uno da java a ruby :)

> Dopo aver creato quasi tutte 
> le istruzioni che mi fanno la conversione,mi manca solo la conversione 
> del record.In dephi il record viene creato cosi:
> 
> type
> persona=record
> età:byte;
> nome:string[50];
> cognome:string[50]:
> professione:strin[55];
> end;
> 
> il quale sono riuscito a convertire.Il problema è che quando viene letto 
> il valore degli elementi del record,il quale viene fatto cosi:
> 
> write (qualcuno.nome,' ',qualcuno.cognome,' ha ',qualcuno.età);
> 
> adesso questa riga deve diventare cosi in ruby:
> 
> print persona.fetch("nome"),' ',persona.fetch("cognome"),' ha 
> ',persona.fetch("eta")
> 
> da come si vede ho pensato di convertire il record in un hash,il quale 
> mi sembrano abbastanza simili

ok


> .A questo punto avevo pensato,per 
> convertire la riga in delphi, che bastava solo che sostuissi soltanto le 
> parti "qualcuno.nome" e le altre due.Per fare ciò ho pensato di creare 
> un if che andasse a cercare "qualcuno" in modo da sostituirlo con 
> "persona.fetch".E qui viene il mio problema...cioè creare il confronto 
> tra "qualcuno"(che è memorizzato in $varrecord) e primariga (che sarebbe 
> la mia espressione),volendo rendere "attivo" $varrecord,visto che non 
> sara sempre "qualcuno".Spero di essere stato chiaro.

bene, ma la regexp che hai scritto

  /:#{$record};/

andrebbe a fare il match di "string[55]" non del nome del record.Puoi però prendere tutti e due usando di nuovo i capturing group

text = "
 type
 persona=record
 eta:byte;
 nome:string[50];
 cognome:string[50];
 professione:string[55];
 end;
" 

elements = text.split("\n")
#questo pezzo già ce l'hai, leggendo una riga per volta

rgx = / (.*):(.*);/ # spazio, nome, ":" valore, ";"
hash = {}
elements.each do |line|
  if m=rgx.match(line)
   hash[m[1]]= m[2]  #un hash {nome=>tipo}
  end
end

p hash #=> {"professione"=>"string[55]", "cognome"=>"string[50]", "nome"=>"string[50]", "eta"=>"byte"}

Ora, suppongo tu abbia una cosa tipo questa

 type
 persona=record
 eta:byte;
 nome:string[50];
 cognome:string[50];
 professione:string[55];
 end;
joe  = ....dichiarazione in delphi del record...
mike  = ....dichiarazione in delphi del record...
write (joe.nome,' ',joe.cognome,' ha ',joe.età);
write (mike.nome,' ',mike.cognome,' ha ',mike.età);

e tu hai il codice che fa 
parse_record_definition (parsa il tipo)
 parse_hash() # parsa joe
 parse_hash() # parsa mike
e ti mancano
 parse_write() # parsa la write di joe
 parse_write() # parsa la write di mike

se si allora ti basta usare gsub, penso

lines = ["write (joe.nome,' ',joe.cognome,' ha ',joe.eta);",
         "write (mike.nome,' ',mike.cognome,' ha ',mike.eta);"]

for line in lines
  puts line.gsub(/
            (\w+) # nome
            \.    # il punto
            (\w+) # il campo del record
            ;    # fine della linea
            /x,   # x serve a definire una regex multilinea con spazi e commenti
            '\1.fetch("\2")')
end

output:
   write (joe.fetch("nome"),' ',joe.fetch("cognome"),' ha ',joe.fetch("eta"));
   write (mike.fetch("nome"),' ',mike.fetch("cognome"),' ha ',mike.fetch("eta"));


dove vedi \1 e \2 che sono ancora i capturing group. Occhio che la stringa è definita con il singolo apice, sennò non funziona perché "\1" è un escape.

Ma ancora meglio: se usi la classe OpenStruct (require 'ostruct') puoi inizializzarla con un hash e poi usare la stessa sintassi dei record in pascal e quindi non devi fare niente :D

>> require 'ostruct'
=> true
>> o=OpenStruct.new('joe'=>1,'mike'=>100)
=> #<OpenStruct mike=100, joe=1>
>> o.joe
=> 1
>> o.mike
=> 100


      


More information about the Ml mailing list