From: Stefano De nigris [email protected]
To: [email protected]
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
end;
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
require ‘ostruct’
=> true
o=OpenStruct.new(‘joe’=>1,‘mike’=>100)
=> #
o.joe
=> 1
o.mike
=> 100