[英]complex regular expression in Java
我有一個相當復雜(對我來說似乎相當復雜)的問題,我在 Java 中使用正則表達式:
我可以得到任何必須采用以下格式的文本字符串:
M:<some text>:D:<either a url or string>:C:<some more text>:Q:<a number>
我從一個正則表達式開始,用於提取M:/:D:/:C:/:Q: 之間的文本:
String pattern2 = "(M:|:D:|:C:|:Q:.*?)([a-zA-Z_\\\\.0-9]+)";
如果<either a url or string>
只是一個字母數字字符串,那么這很好用。 但是當嵌入的字符串是格式的 url 時,一切都會崩潰:
tcp://someurl.something:port
任何人都可以幫我調整上面的 reg exp 以提取:D: 之后的文本是一個 url 或一個字母數字字符串嗎?
下面是一個例子:
public static void main(String[] args) {
String name = "M:myString1:D:tcp://someurl.com:8989:C:myString2:Q:1";
boolean matchFound = false;
ArrayList<String> values = new ArrayList<>();
String pattern2 = "(M:|:D:|:C:|:Q:.*?)([a-zA-Z_\\.0-9]+)";
Matcher m3 = Pattern.compile(pattern2).matcher(name);
while (m3.find()) {
matchFound = true;
String m = m3.group(2);
System.out.println("regex found match: " + m);
values.add(m);
}
}
在上面的例子中,我的結果是:
myString1
tcp://someurl.com:8989
myString2
1
請注意,字符串可以是可變長度的字母數字,但允許某些字符(例如帶有 :// 和/或 . - 字符的 url 格式
你提到格式是不變的:
M:<some text>:D:<either a url or string>:C:<some more text>:Q:<a number>
捕獲組可以使用以下模式為您執行此操作:
"M:(.*):D:(.*):C:(.*):Q:(.*)"
或者您可以使用"M:|:D:|:C:|:Q:"
模式執行String.split()
。 但是,拆分將在第一個索引處返回一個空元素。 其他一切都會隨之而來。
public static void main(String[] args) throws Exception {
System.out.println("Regex: ");
String data = "M:<some text>:D:tcp://someurl.something:port:C:<some more text>:Q:<a number>";
Matcher matcher = Pattern.compile("M:(.*):D:(.*):C:(.*):Q:(.*)").matcher(data);
if (matcher.matches()) {
for (int i = 1; i <= matcher.groupCount(); i++) {
System.out.println(matcher.group(i));
}
}
System.out.println();
System.out.println("String.split(): ");
String[] pieces = data.split("M:|:D:|:C:|:Q:");
for (String piece : pieces) {
System.out.println(piece);
}
}
結果:
Regex:
<some text>
tcp://someurl.something:port
<some more text>
<a number>
String.split():
<some text>
tcp://someurl.something:port
<some more text>
<a number>
要提取 URL/文本部分,您不需要正則表達式。 用
int startPos = input.indexOf(":D:")+":D:".length();
int endPos = input.indexOf(":C:", startPos);
String urlOrText = input.substring(startPos, endPos);
假設您需要在解析的同時進行一些驗證:
將正則表達式分成不同的部分,如下所示:
String m_regex = "[\\w.]+"; //in jsva a . in [] is just a plain dot
String url_regex = "."; //theres a bunch online, pick your favorite.
String d_regex = "(?:" + url_regex + "|\\p{Alnum}+)"; // url or a sequence of alphanumeric characters
String c_regex = "[\\w.]+"; //but i'm assuming you want this to be a bit more strictive. not sure.
String q_regex = "\\d+"; //what sort of number exactly? assuming any string of digits here
String regex = "M:(?<M>" + m_regex + "):"
+ "D:(?<D>" + d_regex + "):"
+ "C:(?<D>" + c_regex + "):"
+ "Q:(?<D>" + q_regex + ")";
Pattern p = Pattern.compile(regex);
將模式作為靜態字段保留在某個地方並在靜態塊中編譯它可能是一個好主意,這樣臨時正則表達式字符串就不會使某些具有基本無用字段的類過度擁擠。
然后您可以按名稱檢索每個部分:
Matcher m = p.matcher( input );
if (m.matches()) {
String m_part = m.group( "M" );
...
String q_part = m.group( "Q" );
}
您可以通過創建 RegexGroup 接口/對象更進一步,其中每個實現對象代表具有名稱和實際正則表達式的正則表達式的一部分。 雖然你肯定會失去簡單性,但快速瀏覽一下就更難理解了。 (我不會這樣做,只是指出它的可能並有其自身的好處)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.