ถ้าฉันมีสตริงแบบนี้:
FOO[BAR]
ฉันต้องการวิธีทั่วไปในการดึงสตริง "BAR" ออกจากสตริงเพื่อไม่ว่าสตริงใดที่อยู่ระหว่างวงเล็บเหลี่ยมก็จะสามารถรับสตริงได้
เช่น
FOO[DOG] = DOG
FOO[CAT] = CAT
ถ้าฉันมีสตริงแบบนี้:
FOO[BAR]
ฉันต้องการวิธีทั่วไปในการดึงสตริง "BAR" ออกจากสตริงเพื่อไม่ว่าสตริงใดที่อยู่ระหว่างวงเล็บเหลี่ยมก็จะสามารถรับสตริงได้
เช่น
FOO[DOG] = DOG
FOO[CAT] = CAT
คำตอบ:
คุณควรจะสามารถใช้ตัวระบุปริมาณที่ไม่โลภโดยเฉพาะ *? คุณอาจต้องการสิ่งต่อไปนี้:
Pattern MY_PATTERN = Pattern.compile("\\[(.*?)\\]");
นี่จะให้รูปแบบที่ตรงกับสตริงของคุณและใส่ข้อความไว้ในวงเล็บเหลี่ยมในกลุ่มแรก ดูเอกสาร Pattern APIสำหรับข้อมูลเพิ่มเติม
ในการแยกสตริงคุณสามารถใช้สิ่งต่อไปนี้:
Matcher m = MY_PATTERN.matcher("FOO[BAR]");
while (m.find()) {
String s = m.group(1);
// s now contains "BAR"
}
วิธีที่ไม่ใช่ regex:
String input = "FOO[BAR]", extracted;
extracted = input.substring(input.indexOf("["),input.indexOf("]"));
หรือเพื่อประสิทธิภาพ / การใช้งานหน่วยความจำที่ดีขึ้นเล็กน้อย (ขอบคุณ Hosam):
String input = "FOO[BAR]", extracted;
extracted = input.substring(input.indexOf('['),input.lastIndexOf(']'));
lastIndexOf(']')
แทนซึ่งจะจัดการกับวงเล็บที่ซ้อนกัน นอกจากนี้ฉันเชื่อว่าการใช้ไฟล์indexOf(char)
จะเร็วกว่าindexOf(String)
.
lastIndexOf
จะเร็วกว่าในการค้นหาวงเล็บปิด
นี่คือตัวอย่างการทำงาน:
RegexpExample.java
package org.regexp.replace;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexpExample
{
public static void main(String[] args)
{
String string = "var1[value1], var2[value2], var3[value3]";
Pattern pattern = Pattern.compile("(\\[)(.*?)(\\])");
Matcher matcher = pattern.matcher(string);
List<String> listMatches = new ArrayList<String>();
while(matcher.find())
{
listMatches.add(matcher.group(2));
}
for(String s : listMatches)
{
System.out.println(s);
}
}
}
จะแสดง:
value1
value2
value3
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public static String get_match(String s, String p) {
// returns first match of p in s for first group in regular expression
Matcher m = Pattern.compile(p).matcher(s);
return m.find() ? m.group(1) : "";
}
get_match("FOO[BAR]", "\\[(.*?)\\]") // returns "BAR"
public static List<String> get_matches(String s, String p) {
// returns all matches of p in s for first group in regular expression
List<String> matches = new ArrayList<String>();
Matcher m = Pattern.compile(p).matcher(s);
while(m.find()) {
matches.add(m.group(1));
}
return matches;
}
get_matches("FOO[BAR] FOO[CAT]", "\\[(.*?)\\]")) // returns [BAR, CAT]
หากคุณต้องการรับสิ่งที่อยู่ระหว่าง[]
คุณสามารถใช้\[([^\]]*)\]
ดังนี้:
Pattern regex = Pattern.compile("\\[([^\\]]*)\\]");
Matcher m = regex.matcher(str);
if (m.find()) {
result = m.group();
}
หากคุณต้องการให้อยู่ในรูปแบบidentifier + [ + content + ]
คุณสามารถ จำกัด การแยกเนื้อหาได้ก็ต่อเมื่อตัวระบุเป็นตัวเลขและตัวอักษร:
[a-zA-Z][a-z-A-Z0-9_]*\s*\[([^\]]*)\]
สิ่งนี้จะตรวจสอบสิ่งต่างๆเช่นFoo [Bar]
หรือmyDevice_123["input"]
ตัวอย่างเช่น
ปัญหาหลัก
ปัญหาหลักคือเมื่อคุณต้องการแยกเนื้อหาของสิ่งนี้:
FOO[BAR[CAT[123]]+DOG[FOO]]
Regex จะไม่ทำงานและจะกลับมาและBAR[CAT[123
ถ้าเราเปลี่ยน Regex เป็นแสดงว่าเราก็โอเค แต่ถ้าคุณพยายามดึงเนื้อหาจากสิ่งที่ซับซ้อนกว่านี้เช่น:FOO
\[(.*)\]
FOO[BAR[CAT[123]]+DOG[FOO]] = myOtherFoo[BAR[5]]
Regexes จะไม่ทำงาน
Regex ที่ถูกต้องที่สุดในการดึงเนื้อหาที่เหมาะสมในทุกกรณีจะซับซ้อนกว่ามากเนื่องจากจะต้องสร้างสมดุลระหว่าง[]
คู่และให้เนื้อหาแก่คุณ
วิธีแก้ปัญหาที่ง่ายกว่า
หากปัญหาของคุณเริ่มซับซ้อนและมีเนื้อหา[]
ตามอำเภอใจคุณสามารถปรับสมดุลคู่ของ[]
และแยกสตริงโดยใช้รหัสเก่าธรรมดาแทน Regex:
int i;
int brackets = 0;
string c;
result = "";
for (i = input.indexOf("["); i < str.length; i++) {
c = str.substring(i, i + 1);
if (c == '[') {
brackets++;
} else if (c == ']') {
brackets--;
if (brackets <= 0)
break;
}
result = result + c;
}
นี่เป็นรหัสหลอกมากกว่ารหัสจริงฉันไม่ใช่โค้ด Java ดังนั้นฉันจึงไม่รู้ว่าไวยากรณ์ถูกต้องหรือไม่ แต่ควรจะง่ายพอที่จะปรับปรุง
สิ่งที่นับได้คือรหัสนี้ควรใช้งานได้และช่วยให้คุณสามารถแยกเนื้อหาของสิ่ง[]
ที่ซับซ้อนได้
ฉันคิดว่าการแสดงออกปกติของคุณจะมีลักษณะดังนี้:
/FOO\[(.+)\]/
สมมติว่า FOO จะคงที่
ดังนั้นหากต้องการใส่สิ่งนี้ใน Java:
Pattern p = Pattern.compile("FOO\\[(.+)\\]");
Matcher m = p.matcher(inputLine);
String input = "FOO[BAR]";
String result = input.substring(input.indexOf("[")+1,input.lastIndexOf("]"));
สิ่งนี้จะคืนค่าระหว่าง "[" ครั้งแรกและครั้งสุดท้าย "]"
Foo [Bar] => บาร์
Foo [Bar [test]] => บาร์ [ทดสอบ]
หมายเหตุ: คุณควรเพิ่มข้อผิดพลาดในการตรวจสอบว่าสตริงอินพุตไม่ถูกต้องหรือไม่
สมมติว่าไม่อนุญาตให้ใช้วงเล็บเหลี่ยมปิดอื่น ๆ ภายใน / FOO \ [([^ \]] *) \] /
ฉันต้องการกำหนดที่ฉันต้องการจำนวนสูงสุดของตัวละครที่ไม่ใช่] ระหว่างและ[
]
สิ่งเหล่านี้จำเป็นต้องหลีกเลี่ยงด้วยแบ็กสแลช (และใน Java จำเป็นต้องใช้ Escape อีกครั้ง) และคำจำกัดความของ non-] คือคลาสอักขระดังนั้นภายใน[
และ]
(เช่น[^\\]]
) ผลลัพธ์:
FOO\\[([^\\]]+)\\]
วิธีนี้ใช้งานได้หากคุณต้องการแยกวิเคราะห์สตริงซึ่งมาจาก mYearInDB.toString () = [2013] มันจะให้ 2013
Matcher n = MY_PATTERN.matcher("FOO[BAR]"+mYearInDB.toString());
while (n.find()) {
extracredYear = n.group(1);
// s now contains "BAR"
}
System.out.println("Extrated output is : "+extracredYear);
regexp นี้ใช้ได้กับฉัน:
form\[([^']*?)\]
ตัวอย่าง:
form[company_details][0][name]
form[company_details][0][common_names][1][title]
เอาต์พุต:
Match 1
1. company_details
Match 2
1. company_details
ทดสอบบนhttp://rubular.com/
"FOO[DOG]".replaceAll("^.*?\\[|\\].*", "");
สิ่งนี้จะส่งคืนสตริงที่รับเฉพาะสตริงที่อยู่ในวงเล็บเหลี่ยม
สิ่งนี้จะลบสตริงทั้งหมดที่อยู่ภายนอกออกจากวงเล็บเหลี่ยม
คุณสามารถทดสอบโค้ดตัวอย่าง java นี้ทางออนไลน์: http://tpcg.io/wZoFu0
คุณสามารถทดสอบ regex ได้จากที่นี่: https://regex101.com/r/oUAzsS/1