แยกสตริงโดยมีจุดเป็นตัวคั่น


100

ฉันสงสัยว่าฉันกำลังจะแยกสตริงอย่าง.ถูกวิธีหรือไม่? รหัสของฉันคือ:

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

ฉันต้องการเพียงส่วนแรกของสตริงนั่นคือเหตุผลที่ฉันส่งคืนรายการแรก ฉันถามเพราะฉันสังเกตเห็นใน API ว่า.หมายถึงอักขระใด ๆ ดังนั้นตอนนี้ฉันติดอยู่

คำตอบ:


175

split()ยอมรับนิพจน์ทั่วไปดังนั้นคุณต้องหลีกเลี่ยง.เพื่อไม่ให้ถือว่าเป็นอักขระเมตา regex นี่คือตัวอย่าง:

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

17

Split ใช้นิพจน์ทั่วไปโดยที่ "." เป็นอักขระพิเศษที่มีความหมายอะไรก็ได้ คุณต้องหนีถ้าคุณต้องการให้ตรงกับ "." ตัวละคร:

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

(หนึ่ง '\' เพื่อหลีกเลี่ยง '.' ในนิพจน์ทั่วไปและอีกตัวหนึ่งเพื่อหลีกเลี่ยงค่าแรกในสตริง Java)

ฉันไม่แนะนำให้ส่งคืน fn [0] เนื่องจากหากคุณมีชื่อไฟล์something.blabla.txtซึ่งเป็นชื่อที่ถูกต้องคุณจะไม่ส่งคืนชื่อไฟล์จริง แต่ฉันคิดว่าจะดีกว่าถ้าคุณใช้:

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

คำถามติดแท็ก Java ไม่ใช่ Javascript ซึ่งเป็นสิ่งที่คุณเชื่อมโยง
Andrei Fierbinteanu

17

ฉันเห็นเฉพาะวิธีแก้ปัญหาที่นี่ แต่ไม่มีคำอธิบายทั้งหมดของปัญหาดังนั้นฉันจึงตัดสินใจโพสต์คำตอบนี้

ปัญหา

text.split(delim)คุณจำเป็นต้องรู้เกี่ยวกับบางสิ่ง splitวิธี:

  1. ยอมรับเป็นนิพจน์ทั่วไปของอาร์กิวเมนต์(regex) ซึ่งอธิบายถึงตัวคั่นที่เราต้องการแยก
  2. หากdelimมีอยู่ในตอนท้ายของtextlike a,b,c,,(โดยที่ตัวคั่นอยู่,) splitในตอนแรกจะสร้างอาร์เรย์เหมือน["a" "b" "c" "" ""]แต่ในกรณีส่วนใหญ่เราไม่ต้องการสตริงว่างต่อท้ายเหล่านี้จริงๆมันจะลบออกโดยอัตโนมัติสำหรับเราด้วย ดังนั้นมันจะสร้างอาร์เรย์อื่นโดยไม่ได้เหล่านี้สตริงว่างต่อท้ายและผลตอบแทนมัน

นอกจากนี้คุณยังจำเป็นต้องรู้ว่าจุด.เป็นอักขระพิเศษในregex แสดงถึงอักขระใด ๆ (ยกเว้นตัวคั่นบรรทัด แต่สามารถเปลี่ยนได้ด้วยPattern.DOTALLแฟล็ก)

ดังนั้นสำหรับสตริงเช่น"abc"ถ้าเราแยก"." splitวิธีจะ

  1. สร้างอาร์เรย์เช่น["" "" "" ""],
  2. แต่เนื่องจากอาร์เรย์นี้มีสตริงว่างเท่านั้นและทุกอย่างต่อท้ายจึงจะถูกลบออก

ซึ่งหมายความว่าเราจะได้อาร์เรย์ว่างเป็นผลลัพธ์[](โดยไม่มีองค์ประกอบหรือแม้แต่สตริงว่างเปล่า) ดังนั้นเราจึงไม่สามารถใช้งานได้fn[0]เนื่องจากไม่มีดัชนี 0

วิธีการแก้

ในการแก้ปัญหานี้คุณต้องสร้าง regex ซึ่งจะแทนจุด ในการทำเช่นนั้นเราจำเป็นต้องหลีกหนีสิ่ง.นั้น มีไม่กี่วิธีในการทำ แต่วิธีที่ง่ายที่สุดคือการใช้\(ซึ่งใน String จำเป็นต้องเขียนเป็น"\\"เพราะ\มีความพิเศษเช่นกันและต้องใช้อีกวิธีหนึ่ง\ในการหลีกเลี่ยง)

ดังนั้นวิธีแก้ปัญหาของคุณอาจมีลักษณะดังนี้

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

โบนัส

คุณยังสามารถใช้วิธีอื่นเพื่อหลีกเลี่ยงจุดนั้นเช่น

  • โดยใช้คลาสอักขระ split("[.]")
  • ห่อไว้ในใบเสนอราคา split("\\Q.\\E")
  • ใช้อินสแตนซ์ Pattern ที่เหมาะสมพร้อมPattern.LITERALแฟล็ก
  • หรือเพียงแค่ใช้split(Pattern.quote("."))และปล่อยให้ regex หลบหนีให้คุณ

อันนี้ .. ชอบมาก: split("[.]")
Dragonborn

15

วิธีการแยกสตริง # (สตริง) ใช้นิพจน์ทั่วไป ในนิพจน์ทั่วไปเครื่องหมาย "." character หมายถึง "อักขระใด ๆ " คุณสามารถหลีกเลี่ยงพฤติกรรมนี้ได้โดยหลีกเลี่ยง "."

filename.split("\\.");

หรือบอกวิธีการแบ่งแยกที่คลาสอักขระ:

filename.split("[.]");

คลาสอักขระคือคอลเล็กชันของตัวละคร คุณสามารถเขียน

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

และชื่อไฟล์จะถูกแบ่งทุก ๆ "-", ".", ";", "l", "d" หรือ "7" ภายในคลาสอักขระ "." ไม่ใช่อักขระพิเศษ ("metacharacter")


@MisterSmith คุณอาจต้องการดูภาษาโปรแกรมที่นี่ เรากำลังพูดถึง java ไม่ใช่ javascript
f1sh

คุณมีสิทธิ์อย่างแน่นอน เมื่อวานฉันเหนื่อยกับการเข้ารหัสทั้งสองภาษาไม่ได้สังเกตประเภทข้อมูล Java ฉันคิดว่าคำตอบอาจถูกต้องในปี 2010 แต่เบราว์เซอร์ในปัจจุบันทำงานในลักษณะที่แตกต่างออกไป
Mister Smith

7

เนื่องจาก DOT (.) ถือเป็นอักขระพิเศษและวิธีการแยกของ String คาดว่าจะมีนิพจน์ทั่วไปที่คุณต้องทำเช่นนี้ -

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

ใน java อักขระพิเศษจำเป็นต้องใช้ Escape ด้วย "\" แต่เนื่องจาก "\" เป็นอักขระพิเศษใน Java ด้วยคุณจึงต้องหลีกเลี่ยงอีกครั้งด้วย "\" อีกตัว!






0

หมายเหตุ: ข้อมูลโค้ดนี้ควรใช้ความระมัดระวังเพิ่มเติมแม้ว่าจุดจะหนีไปแล้วก็ตาม!

หากชื่อไฟล์เป็นเพียงสตริง "." ดังนั้น fn จะยังคงมีความยาวเป็น 0 และ fn [0] จะยังคงมีข้อยกเว้น!

เนื่องจากหากรูปแบบตรงกันอย่างน้อยหนึ่งครั้งการแบ่งจะทิ้งสตริงว่างที่ต่อท้ายทั้งหมด (ซึ่งเป็นสตริงที่อยู่ก่อนจุด!) จากอาร์เรย์โดยปล่อยให้อาร์เรย์ว่างที่จะส่งคืน


วิธีแก้ปัญหาที่ง่ายที่สุดในกรณีเช่นเดียวคือการส่งข้อ จำกัด - อาร์กิวเมนต์ของ 2 ไปยังการเรียกเพื่อแยก: String [] fn = filename.split ("[.]", 2);
avl42


0

การใช้ApacheCommonsนั้นง่ายที่สุด:

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

หมายเหตุนอกจากนี้ยังแยกชื่อไฟล์จากเส้นทางแบบเต็ม


-2

splitใช้ regex เป็นอาร์กิวเมนต์ ดังนั้นคุณควรผ่าน"\."แทนที่จะเป็น"."เพราะ"."เป็นอักขระเมตาในนิพจน์ทั่วไป

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.