2010-03-04 3 views
6

Sto cercando di capire il modo migliore per farlo ...speciale divisione stringa in Ruby

Data una stringa

s = "if someBool || x==1 && y!=22314" 

mi piacerebbe utilizzare Ruby per separare le dichiarazioni e gli operatori booleani .. così mi piacerebbe dividere questo in

["if","someBool","||","x","==","1","&&","y","!=","22314"] 

ho potuto utilizzare s.split(), ma questo solo divide con lo spazio come delimeters..but mi piacerebbe x! = y da dividere troppo (sono frasi booleane valide, semplicemente non hanno spazio in mezzo per una buona leggibilità). Ovviamente il modo più semplice è richiedere all'utente di mettere dello spazio tra operatore booleano e variabili, ma esiste un altro modo per farlo?

risposta

4

Split su spazi bianchi o un limite di parola:

s = "if someBool || x==1 && y!=22314" 
a = s.split(/\s+|\b/); 
p a 

uscita:

["if", "someBool", "||", "x", "==", "1", "&&", "y", "!=", "22314"] 
+0

Sì, lo fa per me. Bello. – Shadowfirebird

1

È possibile ottenere dividere per dividere tutto ciò che si desidera, tra cui un'espressione regolare. Qualcosa di simile:

s.split(/\s|==|!=/) 

... potrebbe essere un inizio.

Disclaimer: regexen mi fa male alla testa. L'ho provato ora e funziona contro il tuo esempio.


AGGIORNAMENTO: No, non lo è. split divide sempre ciò su cui si divide, quindi il codice sopra perde == e! = dal tuo esempio. (Codice Monoceres' funziona bene.)

Ma per qualche ragione, se si racchiudere il termine spaccatura nella regex tra parentesi, mantiene la cosa nella matrice risposta invece di dividere su di esso. Non so se questo è un bug, una funzionalità o un po 'di design intelligente che non apprezzo correttamente.

Quindi, in realtà è necessario:

s.split(/\s|(==)|(!=)/) 

Ma questo non è certo il codice che si spiega. E per quanto ne so non funziona in 1.9.

1

Qualcosa di simile a questo funziona:

s = "12&&32 || 90==12 !=67" 
a = s.split(/ |(\|\|)|(&&)|(!=)|(==)/) 
a.delete("") 
p a 

Per qualche ragione "" rimasti nella matrice, la linea di cancellazione fissa che.

2

La mia regola generale: usa split se sai cosa buttare via (i delimitatori), usa una regex se sai cosa tenere. In questo caso si sa cosa tenere (i gettoni), in modo da:

s.scan(/ \w+ | (?: \s|\b)(?: \|\| | && | [=!]=)(?: \s|\b) /x) 
# => ["if", "someBool", "||", "x", "==", "1", "&&", "y", "!=", "22314"] 

I (?: \s|\b) "delimitatori" sono per evitare che i gettoni (ad esempio ==) dalla corrispondenza qualcosa che non si vuole (ad esempio !==)

+0

Penso che la scansione sia più c-like e probabilmente più efficiente e mi piacerebbe anche attenerci ad essa – Jose

+1

@jocapco, se "c-like" è importante, perché Ruby? –

+0

non è importante, è solo bello :) ..rubino perché quello che sto facendo richiede che l'utente sappia molto poco e faccia molto ... usare un linguaggio di script come il rubino sarebbe preferibile allora. Sto solo facendo ancora cose su piccola scala. – Jose