Tách chuỗi với dấu chấm làm dấu phân cách


99

Tôi đang tự hỏi liệu tôi có định tách một chuỗi .theo cách đúng không? Mã của tôi là:

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

Tôi chỉ cần phần đầu tiên của chuỗi, đó là lý do tại sao tôi trả về mục đầu tiên. Tôi hỏi vì tôi nhận thấy trong API .có nghĩa là bất kỳ ký tự nào, vì vậy bây giờ tôi bị mắc kẹt.

Câu trả lời:


173

split()chấp nhận một biểu thức chính quy, vì vậy bạn cần phải thoát .để không coi nó như một ký tự meta regex. Đây là một ví dụ:

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

17

Split sử dụng cụm từ thông dụng, trong đó '.' là một ký tự đặc biệt có nghĩa là bất cứ điều gì. Bạn cần phải thoát khỏi nó nếu bạn thực sự muốn nó khớp với '.' tính cách:

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

(một '\' để thoát khỏi '.' trong biểu thức chính quy và cái còn lại để thoát khỏi dấu đầu tiên trong chuỗi Java)

Ngoài ra, tôi sẽ không đề xuất trả lại fn [0] vì nếu bạn có tên tệp something.blabla.txt, đó là tên hợp lệ, bạn sẽ không trả lại tên tệp thực. Thay vào đó, tôi nghĩ sẽ tốt hơn nếu bạn sử dụng:

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

Câu hỏi được gắn thẻ Java, không phải Javascript, là những gì bạn đã liên kết đến.
Andrei Fierbinteanu

17

Tôi chỉ thấy các giải pháp ở đây nhưng không có giải thích đầy đủ về vấn đề nên tôi quyết định đăng câu trả lời này

Vấn đề

Bạn cần biết một số điều về text.split(delim). splitphương pháp:

  1. chấp nhận dưới dạng biểu thức chính quy đối số (regex) mô tả dấu phân cách mà chúng ta muốn tách,
  2. nếu delimtồn tại ở cuối textlike in a,b,c,,(nơi có dấu phân cách ,) splitlúc đầu sẽ tạo mảng như thế ["a" "b" "c" "" ""]nhưng vì trong hầu hết các trường hợp, chúng ta không thực sự cần các chuỗi trống theo sau này, nó cũng tự động loại bỏ chúng cho chúng ta. Vì vậy, nó tạo ra một mảng khác không có các chuỗi trống theo sau này và trả về nó .

Bạn cũng cần biết rằng dấu chấm.ký tự đặc biệt trong regex . Nó đại diện cho bất kỳ ký tự nào (ngoại trừ dấu phân cách dòng nhưng điều này có thể được thay đổi bằng Pattern.DOTALLcờ).

Vì vậy, đối với chuỗi như "abc"nếu chúng ta tách trên "." splitphương thức sẽ

  1. tạo mảng như ["" "" "" ""],
  2. nhưng vì mảng này chỉ chứa các chuỗi trống và tất cả chúng đều ở phía sau nên chúng sẽ bị loại bỏ (như được hiển thị trong điểm thứ hai trước đó)

có nghĩa là chúng ta sẽ nhận được kết quả là mảng trống [](không có phần tử, thậm chí không phải chuỗi rỗng), vì vậy chúng ta không thể sử dụng fn[0]vì không có chỉ mục 0.

Giải pháp

Để giải quyết vấn đề này, bạn chỉ cần tạo regex sẽ đại diện cho dấu chấm. Để làm như vậy chúng ta cần phải thoát khỏi điều đó .. Có một số cách để làm điều đó, nhưng đơn giản nhất có lẽ là bằng cách sử dụng \(mà trong Chuỗi cần được viết "\\"\nó cũng đặc biệt ở đó và yêu cầu một cái khác \phải được thoát).

Vì vậy, giải pháp cho vấn đề của bạn có thể trông giống như

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

Tặng kem

Bạn cũng có thể sử dụng các cách khác để thoát khỏi dấu chấm đó như

  • sử dụng lớp ký tự split("[.]")
  • gói nó trong trích dẫn split("\\Q.\\E")
  • sử dụng mẫu phù hợp với Pattern.LITERALcờ
  • hoặc chỉ cần sử dụng split(Pattern.quote("."))và để regex thực hiện việc thoát cho bạn.

cái này .. Tôi thực sự thích: split("[.]")
Dragonborn

15

phương thức String # split (String) sử dụng biểu thức chính quy. Trong biểu thức chính quy, dấu "." ký tự có nghĩa là "bất kỳ ký tự nào". Bạn có thể tránh hành vi này bằng cách thoát khỏi "."

filename.split("\\.");

hoặc yêu cầu phương thức phân tách để tách tại một lớp ký tự:

filename.split("[.]");

Các lớp nhân vật là tập hợp các ký tự. Bạn có thể viết

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

và tên tệp sẽ được phân chia tại mọi "-", ".", ";", "l", "d" hoặc "7". Bên trong các lớp ký tự, dấu "." không phải là một ký tự đặc biệt ("siêu ký tự").


@MisterSmith Bạn có thể muốn xem ngôn ngữ lập trình tại đây. Chúng ta đang nói về java, không phải javascript.
f1sh

Bạn hoàn toàn đúng. Tôi đã rất mệt mỏi vào ngày hôm qua, phải viết mã bằng cả hai ngôn ngữ, không nhận thấy các kiểu dữ liệu Java. Tôi nghĩ có lẽ câu trả lời là đúng vào năm 2010 nhưng bằng cách nào đó các trình duyệt ngày nay hoạt động theo một cách khác.
Mister Smith,

7

Vì DOT (.) Được coi là một ký tự đặc biệt và phương thức phân tách của Chuỗi mong đợi một biểu thức chính quy bạn cần thực hiện như thế này -

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

Trong java, các ký tự đặc biệt cần được thoát bằng "\" nhưng vì "\" cũng là một ký tự đặc biệt trong Java, bạn cần phải thoát nó một lần nữa bằng một "\" khác!



2

Nó sẽ không hiệu quả hơn khi sử dụng

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

nếu bạn chỉ muốn những gì lên đến dấu chấm đầu tiên?


2

Thường thì KHÔNG phải là một ý kiến ​​hay khi vạch mặt nó bằng tay. Có một phương thức trong lớp Mẫu cho tác vụ này:

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

1

Sự phân tách phải lấy regex làm đối số ... Chỉ cần thay đổi "."thành"\\."


0

Lưu ý: Cần cẩn thận hơn với đoạn mã này, ngay cả sau khi dấu chấm bị thoát ra ngoài!

Nếu tên tệp chỉ là chuỗi ".", Thì fn sẽ vẫn có độ dài bằng 0 và fn [0] sẽ vẫn ném ra một ngoại lệ!

Điều này là do nếu mẫu khớp với nhau ít nhất một lần, thì quá trình tách sẽ loại bỏ tất cả các chuỗi trống theo sau (do đó cũng là chuỗi trước dấu chấm!) Khỏi mảng, để lại một mảng trống được trả về.


giải pháp đơn giản nhất trong các trường hợp như trường hợp đang xảy ra là cũng truyền đối số giới hạn là 2 cho lệnh gọi tách: String [] fn = filename.split ("[.]", 2);
avl42, 27/07/18


0

Sử dụng ApacheCommons đơn giản nhất:

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

Lưu ý, nó cũng trích xuất tên tệp từ đường dẫn đầy đủ.


-2

splitlấy regex làm đối số. Vì vậy, bạn nên vượt qua "\."thay "."vì vì "."là một siêu ký tự trong regex.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.