Forum: Italian Ruby user group Confronto usando regexp

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Stefano D. (Guest)
on 2009-03-07 19:40
Ciao ragazzi,io ho un problema che non so come risolverlo.Ho una
variabile che è di tipo globale --> $varrecord,alla quale è assegnata
una parola (qualcuno è la parola).Vorrei creare un if che funzioni
quando il confronto tra la parola e una espressione è giusta,mi spiego
meglio con un esempio:

if /$varrecord/ =~ espressione_qualsiasi
end

Ma facendo in questo non fa altro che fare il confronto tra
l'espressione e $varrecord,invece io voglio che faccia il confronto tra
l'espressione e qualcuno.
Come posso fare per far "commutare" $varrecord in qualcuno??
Alessandro S. (Guest)
on 2009-03-07 20:34
Stefano De nigris wrote:
> Ciao ragazzi,io ho un problema che non so come risolverlo.Ho una
> variabile che è di tipo globale --> $varrecord,alla quale è assegnata
> una parola (qualcuno è la parola).Vorrei creare un if che funzioni
> quando il confronto tra la parola e una espressione è giusta,mi spiego
> meglio con un esempio:
>
> if /$varrecord/ =~ espressione_qualsiasi
> end
>
> Ma facendo in questo non fa altro che fare il confronto tra
> l'espressione e $varrecord,invece io voglio che faccia il confronto tra
> l'espressione e qualcuno.
> Come posso fare per far "commutare" $varrecord in qualcuno??

il confronto è chiaramente fatto tra il valore di $varrecord e
l'espressione, se il valore è qualcuno il confronto è fatto tra qualcuno
e l'espressione
Pietro G. (Guest)
on 2009-03-07 20:54
(Received via mailing list)
2009/3/7 Stefano De nigris <removed_email_address@domain.invalid>:
> l'espressione e $varrecord,invece io voglio che faccia il confronto tra
> l'espressione e qualcuno.
> Come posso fare per far "commutare" $varrecord in qualcuno??


qualcuno, in questo caso, cos'è? una variabile locale?

vediamo se ho capito: se $varrecord vale 'ciccio', vuoi confrontare la
variabile ciccio? o la variabile $ciccio?

o non ho capito niente?

ad ogni modo, per quello che ne so, l'unico modo è usare eval($varrecord).

pietro
gabriele renzi (Guest)
on 2009-03-07 22:00
(Received via mailing list)
> From: Stefano De nigris <removed_email_address@domain.invalid>
> To: removed_email_address@domain.invalid
> Sent: Saturday, 7 March, 2009 18:40:40
> Subject: [ruby-it] Confronto usando regexp
>
> Ciao ragazzi,io ho un problema che non so come risolverlo.Ho una
> variabile che è di tipo globale --> $varrecord,alla quale è assegnata
> una parola (qualcuno è la parola).Vorrei creare un if che funzioni
> quando il confronto tra la parola e una espressione è giusta,mi spiego
> meglio con un esempio:

è più facile se pensi un passo per volta :)
Hai $varrecord che è una stringa e vorresti che fosse una expressione
regolare.

Quello che vuoi quindi è creare una *nuova Regexp*  :)

>> var="123"
=> "123"
>> rgx= Regexp.new(var)
=> /123/
>> rgx.match("123")
=> #<MatchData "123">

Oppure, usando l'interpolazione come fai per le stringhe

>> /#{var}/ =~ "123"
=>0

che significa "match allo zeresimo carattere"

Attenzione però, che se fai in questo modo il valore della variabile
è considerato come se fosse scritto nel codice:

>> var= "..."
=> "..."
>> /#{var}/ =~ "123"
=> 0

il pounto è il metacarattere che matcha qualsiasi cosa quindi matcha 1,2 e
3.
Se tu invece avessi voluto che il punto fosse considerato letteralmente
come il carattere punto avresti dovuto "quotarlo"

>> rgx= Regexp.new(var)
=> /.../

metacaratteri

>> rgx= Regexp.new(Regexp.quote(var))
=> /\.\.\./

letterali

>> rgx =~ "123"
=> nil
>> rgx =~ "..."
=> 0

E puoi usare il quoting anche dentro l'interpolazione

>> /#{Regexp.quote var}/ =~ "..."
=> 0
>> /#{Regexp.quote var}/ =~ "123"
=> nil


_puoi_ anche usare eval, ma è sempre meglio evitarlo finché possibile  (ed
in generale, è pure meglio evitare le variabili globali)
Stefano D. (Guest)
on 2009-03-10 12:57
Ragazzi quando faccio:
puts $varrecord
mi esce:
qualcuno
percio in $varrecord è memorizzato qualcuno(che è una semplice parola o
meglio una stringa).Quindi il confronto che voglio è tra qualcuno e
l'espressione.

>/#{var}/ =~ "123"
gabriele ho provato a fare cosi ma non funziona,cioè mi esegue l'if
comunque e non se è vero o falso il confronto.
Spero di avervi fatto capire,se avete ancora dubbi non esitate a
chiedere.

Ciao a tutti!!!
Alessandro S. (Guest)
on 2009-03-10 13:20
Stefano De nigris wrote:
> Ragazzi quando faccio:
> puts $varrecord
> mi esce:
> qualcuno
> percio in $varrecord è memorizzato qualcuno(che è una semplice parola o
> meglio una stringa).Quindi il confronto che voglio è tra qualcuno e
> l'espressione.
>
>>/#{var}/ =~ "123"
> gabriele ho provato a fare cosi ma non funziona,cioè mi esegue l'if
> comunque e non se è vero o falso il confronto.
> Spero di avervi fatto capire,se avete ancora dubbi non esitate a
> chiedere.
>
> Ciao a tutti!!!

non è che hai sbagliato la regex?
Stefano D. (Guest)
on 2009-03-11 22:34
> non è che hai sbagliato la regex?
In che senso??Io ho fatto come ho scritto all'inizio,e non credo di aver
commesso errori.

Ciao a tutti!!!!
Alessandro S. (Guest)
on 2009-03-12 00:31
Se vuoi risposte devi dare informazioni leggibili e chiare...

la variabile "espressione_qualsiasi"  che valore assume?? puoi postare
un esempio....



Stefano De nigris wrote:
>> non è che hai sbagliato la regex?
> In che senso??Io ho fatto come ho scritto all'inizio,e non credo di aver
> commesso errori.
>
> Ciao a tutti!!!!
Stefano D. (Guest)
on 2009-03-12 17:06
Ale ecco qui un esempio ... :)
io ho questo:

primariga="write (qualcuno.nome,' ',qualcuno.cognome,' ha
',qualcuno.età);"
$varrecord="qualcuno"

if /#{$varrecord}/ =~ primariga.join(" ")
...e qui dentro vai il codice che deve eseguire...
end

Ho fatto primariga.join(" ") perche primariga è un array,altrimenti non
posso fare il confronto in quanto deve essere una stringa.
Io voglio che al posto di /#{$varrecord}/ deve comparire quello che c'è
in $varrecord(in questo caso "qualcuno"),cioè che venga fatta il
confronto tra "qualcuno" e quello che c'è in primariga.
Il mio problema è che facendo cosi lui mi fa l'if sempre, e non quando
c'è qualcuno.Se avete altri dubbi chiedete???
Pietro G. (Guest)
on 2009-03-12 19:43
(Received via mailing list)
2009/3/12 Stefano De nigris <removed_email_address@domain.invalid>:
> Ale ecco qui un esempio ... :)
> io ho questo:
>
> 1 primariga="write (qualcuno.nome,' ',qualcuno.cognome,' ha ',qualcuno.età);"
> 2 $varrecord="qualcuno"
> 3
> 4 if /#{$varrecord}/ =~ primariga.join(" ")
> 5 ...e qui dentro vai il codice che deve eseguire...
> 6 end


> Ho fatto primariga.join(" ") perche primariga è un array, altrimenti non
> posso fare il confronto in quanto deve essere una stringa.

alla riga 1, viene definita una stringa, non un array.

qualcuno che valore ha?

chi lo assegna?

ma soprattutto: perché mai usi una variabile globale? e, per di
più,una variabile globale che contiene il nome di una variabile (a sua
volta globale? locale? cosa?) che contiene una regular expression o
una stringa...


qualunque sia il problema da risolvere, puoi sicuramente risolverlo
senza variabili globali, con un codice più semplice e comprensibile.


un consiglio: non sempre è utile chiedere aiuto solo sui singoli passi
e basta; spesso si ottengono migliori risultati spiegando il problema:
non è detto che la soluzione a cui hai pensato sia sempre la migliore.


pietro
Stefano D. (Guest)
on 2009-03-13 14:45
> 1 primariga="write (qualcuno.nome,' ',qualcuno.cognome,' ha ',qualcuno.et�);"
Fatta in questo modo è una stringa,ma io ho scritto direttamente cosi in
modo da farvi capire cosa c'è dentro a primariga.Comunque ti assicuro
che primariga è una array,perche è stato creato array per vari motivi.

> qualcuno che valore ha?
qualcuno non ha nessun valore,è semplicemente qualcuno(come ho scritto
prima:$varrecord="qualcuno" quindi una stringa).$varrecord l'ho
assegnato in una altro blocco di codice e serve anche per altri blocchi
di codice,perciò è una variabile globale.

> chi lo assegna?

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

dove $record è una altra variabile in cui c'è memorizzata una
stringa.Elementi1 è il primo elemento di primariga(cioè:
elementi1=primariga[1]).Cosi ho creato $varrecord.

> qualunque sia il problema da risolvere, puoi sicuramente risolverlo
> senza variabili globali, con un codice pi� semplice e comprensibile.

E come potrei??

> un consiglio: non sempre � utile chiedere aiuto solo sui singoli passi
> e basta; spesso si ottengono migliori risultati spiegando il problema:
> non � detto che la soluzione a cui hai pensato sia sempre la migliore.

Beh allora ti dico il mio problema...io ho creato un programma che deve
convertire le istruzioni da delphi in 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.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.

Ciao a tutti!!!!
gabriele renzi (Guest)
on 2009-03-16 19:04
(Received via mailing list)
> From: Stefano De nigris <removed_email_address@domain.invalid>
> To: removed_email_address@domain.invalid
> 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 :D

>> require 'ostruct'
=> true
>> o=OpenStruct.new('joe'=>1,'mike'=>100)
=> #<OpenStruct mike=100, joe=1>
>> o.joe
=> 1
>> o.mike
=> 100
Stefano D. (Guest)
on 2009-03-25 19:44
Gabriele ti ringrazio per l'aiuto,credo che la tua soluzione con qualche
piccola modifica vada bene.Un ultima cosa...come faccio a far fare un
confronto tra uno spazio (" ") e un elemento,che è fatto da uno spazio
vuoto??Mi spiego meglio.
Ho la variabile elemento che è fatta cosi:
elemento=[" "]
e voglio fare un confronto tra:

if [" "] =~ elemento
puts "ciao"
end

credo che in teoria dovrebbe andare cosi,ma mandando in esecuzione non
mi scrive ciao,anzi non mi scrive nulla come se il confronto dasse esito
negativo.Cosa e dove sbaglio???
Stefano D. (Guest)
on 2009-03-25 20:11
Ragazzi risolto già.Mi ero un attimo rimbambito.:D

Ciao a tutti!!!!!
Stefano D. (Guest)
on 2009-03-26 20:24
Gabriele senti io ho un problema.Nelle istruzioni che mi hai dato tu:
>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
questo codice funziona se in elements vi è memorizzato tutto il testo.Ma
il programma che ho realizzato io,si prende una linea di codice per
volta e lo analizza,quindi non si prende tutto il codice ma solo le
singole linee..le analizze e le converte,poi passa alla linea
successiva.Capito?
Adesso come posso modificare questo tuo codice affinche vada bene per il
mio caso???
This topic is locked and can not be replied to.