Stringa divisa con punto come delimitatore


99

Mi chiedo se sto per dividere una corda nel .modo giusto? Il mio codice è:

String[] fn = filename.split(".");
return fn[0];

Mi serve solo la prima parte della stringa, ecco perché restituisco il primo articolo. Chiedo perché ho notato nell'API che .significa qualsiasi carattere, quindi ora sono bloccato.

Risposte:


173

split()accetta un'espressione regolare, quindi è necessario eseguire l'escape .per non considerarlo come un metacarattere regex. Ecco un esempio:

String[] fn = filename.split("\\."); 
return fn[0];

17

Split utilizza espressioni regolari, dove "." è un carattere speciale che significa qualsiasi cosa. È necessario eseguire l'escape se si desidera effettivamente che corrisponda a "." carattere:

String[] fn = filename.split("\\.");

(uno "\" per eseguire l'escape di "." nell'espressione regolare e l'altro per eseguire l'escape del primo nella stringa Java)

Inoltre non suggerirei di restituire fn [0] poiché se si dispone di un file denominato something.blabla.txt, che è un nome valido, non verrà restituito il nome del file effettivo. Invece penso che sia meglio se usi:

int idx = filename.lastIndexOf('.');
return filename.subString(0, idx);

La domanda è etichettata Java, non Javascript, che è ciò a cui ti sei collegato.
Andrei Fierbinteanu

17

Vedo solo soluzioni qui ma nessuna spiegazione completa del problema, quindi ho deciso di pubblicare questa risposta

Problema

Hai bisogno di sapere poche cose su text.split(delim). splitmetodo:

  1. accetta come argomento l'espressione regolare (regex) che descrive il delimitatore su cui vogliamo dividere,
  2. se delimesiste alla fine di textcome in a,b,c,,(dove si trova il delimitatore ,) splitall'inizio creerà un array simile ["a" "b" "c" "" ""]ma poiché nella maggior parte dei casi non abbiamo davvero bisogno di queste stringhe vuote finali, le rimuove automaticamente anche per noi. Quindi crea un altro array senza queste stringhe vuote finali e lo restituisce .

Devi anche sapere che il punto. è un carattere speciale in regex . Rappresenta qualsiasi carattere (tranne i separatori di riga ma questo può essere modificato con Pattern.DOTALLflag).

Quindi per le stringhe come "abc"se dividessimo il "." splitmetodo lo farà

  1. creare array come ["" "" "" ""],
  2. ma poiché questo array contiene solo stringhe vuote e sono tutte finali, verranno rimosse (come mostrato nel secondo punto precedente)

il che significa che otterremo come risultato un array vuoto [](senza elementi, nemmeno una stringa vuota), quindi non possiamo usarlo fn[0]perché non c'è indice 0.

Soluzione

Per risolvere questo problema devi semplicemente creare una regex che rappresenterà il punto. Per farlo dobbiamo evitarlo .. Ci sono pochi modi per farlo, ma il più semplice è probabilmente usando \(che in String deve essere scritto come "\\"perché \è anche speciale lì e richiede un altro \di cui eseguire l'escape).

Quindi la soluzione al tuo problema potrebbe assomigliare

String[] fn = filename.split("\\.");

Bonus

Puoi anche usare altri modi per sfuggire a quel punto come

  • utilizzando la classe di caratteri split("[.]")
  • avvolgendolo in citazione split("\\Q.\\E")
  • utilizzando un'istanza di Pattern corretta con Pattern.LITERALflag
  • o semplicemente usa split(Pattern.quote("."))e lascia che le espressioni regolari escano per te.

questo .. mi piace molto il: split("[.]")
Dragonborn

15

il metodo String # split (String) utilizza espressioni regolari. Nelle espressioni regolari, il "." carattere significa "qualsiasi carattere". Puoi evitare questo comportamento sfuggendo al "."

filename.split("\\.");

o dicendo al metodo split di dividere in una classe di caratteri:

filename.split("[.]");

Le classi di caratteri sono raccolte di caratteri. Potresti scrivere

filename.split("[-.;ld7]");

e il nome del file verrebbe diviso ogni "-", ".", ";", "l", "d" o "7". All'interno delle classi di personaggi, il "." non è un carattere speciale ("metacarattere").


@MisterSmith Potresti voler dare un'occhiata al linguaggio di programmazione qui. Stiamo parlando di java, non di javascript.
f1sh

Hai assolutamente ragione. Ero stanco ieri, avendo programmato in entrambe le lingue, non ho notato i tipi di dati Java. Pensavo che forse le risposte fossero corrette nel 2010, ma in qualche modo i browser oggi si sono comportati in modo diverso.
Mister Smith

7

Poiché DOT (.) È considerato un carattere speciale e il metodo di divisione di String si aspetta un'espressione regolare che devi fare in questo modo:

String[] fn = filename.split("\\.");
return fn[0];

In java i caratteri speciali devono essere preceduti da una "\" ma poiché "\" è anche un carattere speciale in Java, è necessario eseguire di nuovo l'escape con un altro "\"!



2

Non sarebbe più efficiente da usare

 filename.substring(0, filename.indexOf("."))

se vuoi solo cosa succede al primo punto?


2

Di solito NON è una buona idea smascherarlo a mano. C'è un metodo nella classe Pattern per questa attività:

java.util.regex
static String quote(String s) 

1

La divisione deve prendere la regex come argomento ... Cambia semplicemente "."in"\\."


0

Nota: è necessario prestare maggiore attenzione con questo frammento, anche dopo che il punto è sfuggito!

Se filename è solo la stringa ".", Allora fn sarà ancora di lunghezza 0 e fn [0] genererà comunque un'eccezione!

Questo perché se il pattern corrisponde almeno una volta, split scarterà tutte le stringhe vuote finali (quindi anche quella prima del punto!) Dall'array, lasciando un array vuoto da restituire.


La soluzione più semplice in casi come quello in questione è passare anche un argomento limite di 2 alla chiamata a split: String [] fn = filename.split ("[.]", 2);
avl42

0

La soluzione che ha funzionato per me è la seguente

nomefile.split ("[.]");


0

Usare ApacheCommons è più semplice:

File file = ...
FilenameUtils.getBaseName(file.getName());

Nota, estrae anche un nome file dal percorso completo.


-2

splitaccetta una regex come argomento. Quindi dovresti passare "\."invece di "."perché "."è un metacarattere in regex.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.