2013-04-30 14 views
6

Ho appena scoperto il seguente comportamento strano con String#split:Perché split ('') sta cercando di essere (troppo) intelligente?

"a\tb c\nd".split 
=> ["a", "b", "c", "d"] 

"a\tb c\nd".split(' ') 
=> ["a", "b", "c", "d"] 

"a\tb c\nd".split(/ /) 
=> ["a\tb", "c\nd"] 

The source (string.c da 2.0.0) è lunga più di 200 linee e contiene un passaggio come questo:

/* L 5909 */ 
else if (rb_enc_asciicompat(enc2) == 1) { 
    if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' '){ 
     split_type = awk; 
    } 
} 

Più tardi, nel codice per il tipo di split awk, l'argomento effettivo non viene nemmeno più utilizzato e fa lo stesso di un semplice split.

  • Qualcun altro ritiene che questo sia in qualche modo rotto?
  • Ci sono dei buoni motivi?
  • La "magia" come quella si verifica più spesso di quanto la maggior parte della gente possa pensare in Ruby?
+0

Perché è qualcosa che è documentato essere "troppo intelligente"? È un comportamento predefinito previsto che è possibile ignorare se si sceglie di passarlo a un modello alternativo da utilizzare per suddividere il testo. –

+0

Con troppo intelligente intendo dire rubino che voglio dividere a tutti i caratteri degli spazi bianchi, dove sto letteralmente dicendo di dividere in spazi. –

+0

Voterò per chiudere questa domanda poiché mi sto rendendo conto che probabilmente non c'è una risposta generale e soddisfacente a questa domanda. Grazie per tutte le vostre risposte e commenti! –

risposta

4

E 'coerente con split() il comportamento di Perl. Che a sua volta si basa su Gnu awk'ssplit(). Quindi è una tradizione di lunga data con origini in Unix.

Dal perldoc su split:

Come altro caso speciale, spaccata emula il comportamento predefinito del comando strumento linea awk Quando il modello è o omesso o un stringa letterale composto da un singolo carattere spazio (come "" o "\ x20", ma non per es.//). In questo caso, qualsiasi spazio in ESPR viene rimosso prima che si verifichi scissione, e il pattern è invece trattata come se fosse /\ s + /; in particolare, ciò significa che qualsiasi spazio bianco contiguo (non solo un singolo carattere di spazio) viene utilizzato come separatore. Tuttavia, questo trattamento speciale può essere evitato specificando il modello // invece che la stringa "", consentendo in tal modo un singolo carattere spazio per essere un separatore.

+1

Ho giocato un po 'con la divisione di Perl e ho notato che questo ha un senso in Perl, perché ha bisogno di un argomento. Una stringa vuota non funzionerebbe perché questo è un altro caso speciale (restituisce un array di caratteri, come in ruby). La cosa più vicina a chiamare split senza un argomento in Perl era 'split (undef, $ str)' ma in realtà si comporta come 'split ('', $ str)', non come 'split ('', $ str)' così Immagino che non sia abbastanza coerente :). Dopotutto, discutendo sul perché le cose siano così e che in Perl fosse già stato fatto troppo spesso così mi fermerò qui :) –

+0

La tua risposta è ancora la migliore quindi la accetterò. Grazie! –

+0

Storia interessante. – davogones

2

Scopri i documentation, questa parte in particolare:

Se pattern è una stringa, quindi il suo contenuto sono utilizzati come delimitatore quando spacca str. Se modello è un singolo spazio, str è divisa su spazi, con uno spazio vuoto e corre di spazi contigui caratteri ignorati.

Se modello viene omesso, il valore di $; si usa. Se $; è nil (che è di default), str è diviso in spazi bianchi come se fosse stato specificato "".

È possibile utilizzare un regexp per dividere la stringa.

+0

Grazie! Ho letto la documentazione. La mia domanda è più come "Dovremmo andare a risolvere questo problema, o c'è una buona ragione per questo?" –

+0

Almeno sappiamo che è destinato. Possiamo provare a trovare il motivo per cui Matz ha progettato così, e possiamo anche affermare che questo è strano. Ma non puoi "andare a sistemarlo". Chi decide è Matz. – sawa

+0

Ovviamente Matz decide sul futuro della risonanza magnetica. Ma possiamo ancora avvicinarlo a un possibile miglioramento;) –

Problemi correlati