Podzielony ciąg z kropką jako separatorem

100

Zastanawiam się, czy mam zamiar rozłupać sznurek .we właściwy sposób? Mój kod to:

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

Potrzebuję tylko pierwszej części ciągu, dlatego zwracam pierwszą pozycję. Pytam, ponieważ zauważyłem w API, że .oznacza to dowolny znak, więc teraz utknąłem.

Dziekan
źródło

Odpowiedzi:

174

split()akceptuje wyrażenie regularne, więc musisz uciec, .aby nie traktować go jako meta znaku regex. Oto przykład:

String[] fn = filename.split("\\."); 
return fn[0];
Marimuthu Madasamy
źródło
17

Split używa wyrażeń regularnych, gdzie „.” to znak specjalny, który ma znaczenie. Musisz od niego uciec, jeśli chcesz, aby pasował do znaku „.” postać:

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

(jeden „\”, aby zmienić znaczenie „.” w wyrażeniu regularnym, a drugi, aby zmienić znaczenie pierwszego w ciągu Java)

Nie sugerowałbym również zwracania fn [0], ponieważ jeśli masz plik o nazwie something.blabla.txt, która jest prawidłową nazwą, nie zwrócisz rzeczywistej nazwy pliku. Zamiast tego myślę, że lepiej, jeśli używasz:

int idx = filename.lastIndexOf('.');
return filename.subString(0, idx);
Andrei Fierbinteanu
źródło
Pytanie jest oznaczone jako Java, a nie Javascript, do którego utworzyłeś link.
Andrei Fierbinteanu
17

Widzę tutaj tylko rozwiązania, ale nie mam pełnego wyjaśnienia problemu, więc zdecydowałem się opublikować tę odpowiedź

Problem

Musisz wiedzieć kilka rzeczy o text.split(delim). splitmetoda:

  1. akceptuje jako argument wyrażenie regularne (regex), które opisuje ogranicznik, według którego chcemy podzielić,
  2. jeśli delimistnieje na końcu textjak in a,b,c,,(gdzie separator jest ,) splitna początku utworzy tablicę, ["a" "b" "c" "" ""]ale ponieważ w większości przypadków tak naprawdę nie potrzebujemy tych końcowych pustych ciągów, usuwa je również automatycznie za nas. Więc tworzy kolejną tablicę bez tych końcowych pustych ciągów i zwraca ją .

Musisz również wiedzieć, że kropka. jest znakiem specjalnym w wyrażeniu regularnym . Reprezentuje dowolny znak (z wyjątkiem separatorów linii, ale można to zmienić za pomocąPattern.DOTALL flagi).

Więc dla stringów, tak "abc"jakbyśmy podzielili się "." splitmetodą will

  1. stworzyć tablicę jak ["" "" "" ""],
  2. ale ponieważ ta tablica zawiera tylko puste ciągi i wszystkie są końcowe, zostaną usunięte (jak pokazano w poprzednim drugim punkcie)

co oznacza, że ​​w rezultacie otrzymamy pustą tablicę [](bez elementów, nawet bez pustego łańcucha), więc nie możemy jej użyćfn[0] ponieważ nie ma indeksu 0.

Rozwiązanie

Aby rozwiązać ten problem, wystarczy utworzyć wyrażenie regularne, które będzie reprezentować kropkę. Aby to zrobić, musimy uciec od tego .. Jest na to kilka sposobów, ale najprościej jest prawdopodobnie użyć \(co w String musi być zapisane jako, "\\"ponieważ \jest tam również specjalne i wymaga innego\ znaku ucieczki).

Więc może wyglądać rozwiązanie twojego problemu

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

Premia

Możesz także użyć innych sposobów ucieczki przed tą kropką, np

  • za pomocą klasy znaków split("[.]")
  • zawijając go w cytat split("\\Q.\\E")
  • użycie właściwej instancji Patternu z Pattern.LITERALflagą
  • lub po prostu użyj split(Pattern.quote("."))i pozwól regex na ucieczkę za Ciebie.
Pshemo
źródło
to .. bardzo mi się podoba: split("[.]")
Dragonborn
15

metoda String # split (String) używa wyrażeń regularnych. W wyrażeniach regularnych znak „.” znak oznacza „dowolny znak”. Możesz uniknąć tego zachowania, zapisując znak „.”

filename.split("\\.");

lub nakazując metodzie split podział na klasę znaków:

filename.split("[.]");

Klasy znaków to zbiory znaków. Możesz pisać

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

a nazwa pliku będzie dzielona co „-”, „.”, „;”, „l”, „d” lub „7”. W klasach znaków znak „.” nie jest znakiem specjalnym („metaznakiem”).

f1sh
źródło
@MisterSmith Możesz rzucić okiem na język programowania tutaj. Mówimy o javie, a nie javascript.
f1sh
Masz absolutną rację. Wczoraj byłem zmęczony, ponieważ kodowałem w obu językach, nie zauważyłem typów danych Javy. Myślałem, że być może odpowiedzi były poprawne w 2010 roku, ale w jakiś sposób dzisiejsze przeglądarki zachowywały się w inny sposób.
Mister Smith
7

Ponieważ DOT (.) Jest traktowany jako znak specjalny, a metoda split metody String oczekuje wyrażenia regularnego, które należy zrobić w ten sposób -

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

W Javie znaki specjalne muszą być poprzedzone znakiem „\”, ale ponieważ „\” jest również znakiem specjalnym w Javie, należy go ponownie zmienić za pomocą innego znaku „\”!

Neel
źródło
3
String str="1.2.3";
String[] cats = str.split(Pattern.quote("."));
Magnus Persson
źródło
2

Czy nie byłoby bardziej wydajne w użyciu

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

jeśli chcesz tylko, co jest do pierwszej kropki?

Martin Smith
źródło
2

Zwykle ręczne zdejmowanie maski nie jest dobrym pomysłem. W klasie Pattern istnieje metoda służąca do tego zadania:

java.util.regex
static String quote(String s) 
Christian Ullenboom
źródło
1

Podział musi przyjmować wyrażenie regularne jako argument ... Po prostu zmień "."na"\\."

Bob Fincheimer
źródło
0

Uwaga: należy zachować ostrożność z tym fragmentem, nawet po usunięciu kropki!

Jeśli nazwa pliku to tylko ciąg „.”, To fn nadal będzie mieć długość 0, a fn [0] nadal będzie zgłaszać wyjątek!

Dzieje się tak, ponieważ jeśli wzorzec pasuje co najmniej raz, split odrzuci wszystkie końcowe puste ciągi (a więc także ten przed kropką!) Z tablicy, pozostawiając pustą tablicę do zwrócenia.

avl42
źródło
najłatwiejszym rozwiązaniem w takich przypadkach jak ten pod ręką jest również przekazanie argumentu ograniczającego 2 do wywołania split: String [] fn = filename.split ("[.]", 2);
avl42
0

Rozwiązanie, które zadziałało dla mnie, jest następujące

filename.split ("[.]");

jorge santos
źródło
0

Korzystanie z ApacheCommons jest najprostsze:

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

Zauważ, że wyodrębnia również nazwę pliku z pełnej ścieżki.

Nikita
źródło
-2

splitprzyjmuje wyrażenie regularne jako argument. Więc powinieneś podać "\."zamiast, "."ponieważ "."jest metaznakiem w wyrażeniu regularnym.

Vijay Mathew
źródło