[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