Використання Java для пошуку підрядків більшої рядки за допомогою регулярного вираження


140

Якщо у мене є такий рядок:

FOO[BAR]

Мені потрібен загальний спосіб вивести рядок "BAR" з рядка, так що незалежно від того, яка рядок знаходиться між квадратними дужками, вона змогла б отримати рядок.

напр

FOO[DOG] = DOG
FOO[CAT] = CAT

Відповіді:


253

Ви повинні мати можливість використовувати не жадібні квантори, зокрема * ?. Ви, ймовірно, хочете наступного:

Pattern MY_PATTERN = Pattern.compile("\\[(.*?)\\]");

Це дасть вам шаблон, який буде відповідати вашому рядку і помістить текст у квадратні дужки у першій групі. Перегляньте Документацію API API для отримання додаткової інформації.

Щоб витягти рядок, ви можете використовувати щось на зразок наступного:

Matcher m = MY_PATTERN.matcher("FOO[BAR]");
while (m.find()) {
    String s = m.group(1);
    // s now contains "BAR"
}

16
Варто згадати, що якщо між квадратними дужками є нова лінія, це не вдасться, і вам слід використовувати прапор Pattern.DOTALL, щоб уникнути цього.
клент

Використовуючи вищезазначений зразок, як би ви використовували це для вилучення рядка, що містить рядок BAR? Я переглядаю API шаблону та API Matcher, але я все ще не впевнений, як отримати сам рядок.
digiarnie

@cletus: Добрий дзвінок! @digiarnie: Я відповів до редакції відповіді, яка містить деякий солом'яний код для отримання відповідності.
Брайан Кайл

30

нерегекс-спосіб:

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(']'));

1
Я використовував би lastIndexOf(']')замість цього, який би обробляв вкладені дужки. Крім того, я вважаю, що використання цього indexOf(char)було б швидше, ніж indexOf(String).
Хосам Алі

Ласкаво просимо. Ваша примітка щодо продуктивності також дуже актуальна, оскільки lastIndexOf, безумовно, буде швидше знайти дужку закриття.
Хосам Алі

3
що швидше, indexof підрядка тощо тощо або regexp?
Тоскан

2
див. значення Amit для "добутого" нижче: input.indexOf ('[') + 1
gcbound

28

Це робочий приклад:

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

6
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]

5

Якщо вам просто потрібно отримати все, що між ними [], ви можете використовувати \[([^\]]*)\]так:

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і FOO.
Якщо ми змінимо Regex, \[(.*)\]тоді ми все в порядку, але тоді, якщо ви намагаєтеся витягнути вміст із складніших речей, таких як:

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, тому не знаю, чи правильний синтаксис, але це повинно бути досить легким для вдосконалення.
Що враховує, що цей код повинен працювати і дозволяти витягувати вміст [], як би він не був складним.


2

Я думаю, що ваш регулярний вираз виглядатиме так:

/FOO\[(.+)\]/

Припускаючи, що FOO буде постійним.

Отже, щоб сказати це на Java:

Pattern p = Pattern.compile("FOO\\[(.+)\\]");
Matcher m = p.matcher(inputLine);

FOO [BAR] FOO [BAZ] -> з вашим регулярним виразом повернеться: "BAR] FOO [BAZ"
Mohammad Jafar Mashhadi

1
String input = "FOO[BAR]";
String result = input.substring(input.indexOf("[")+1,input.lastIndexOf("]"));

Це поверне значення між першим '[' та останнім ']'

Foo [Bar] => Бар

Foo [Бар [тест]] => Панель [тест]

Примітка. Ви повинні додати перевірку помилок, якщо вхідний рядок не сформований належним чином.


0

якщо припустити, що жодна інша закрита квадратна дужка не дозволена в межах, / FOO \ [([^ \]] *) \] /


0

Я б визначив, що мені потрібно максимальну кількість символів, що не] між [та ]. Їх потрібно уникнути за допомогою косої риски (і на Java, їх потрібно уникнути знову), а визначення non-] є класом символів, таким чином, всередині [і ](тобто [^\\]]). Результат:

FOO\\[([^\\]]+)\\]

0

Подобається це його роботі, якщо ви хочете проаналізувати деякий рядок, який надходить від 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);

0

Цей регепс працює для мене:

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/


0
"FOO[DOG]".replaceAll("^.*?\\[|\\].*", "");

Це поверне рядок із лише рядком всередині квадратних дужок.

Це видалить всю рядок зовні з квадратних дужок.

Ви можете перевірити цей зразок коду Java онлайн: http://tpcg.io/wZoFu0

Ви можете протестувати цей регекс звідси: https://regex101.com/r/oUAzsS/1

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.