Как извлечь подстроку с помощью регулярных выражений

382

У меня есть строка с двумя одинарными кавычками, 'символ. Между одинарными кавычками находятся данные, которые я хочу.

Как я могу написать регулярное выражение, чтобы извлечь "данные, которые я хочу" из следующего текста?

mydata = "some string with 'the data i want' inside";
Asdasd
источник

Ответы:

569

Предполагая, что вы хотите разделить одинарные кавычки, используйте это регулярное выражение с Matcher:

"'(.*?)'"

Пример:

String mydata = "some string with 'the data i want' inside";
Pattern pattern = Pattern.compile("'(.*?)'");
Matcher matcher = pattern.matcher(mydata);
if (matcher.find())
{
    System.out.println(matcher.group(1));
}

Результат:

данные, которые я хочу
Марк Байерс
источник
12
блин .. я всегда забываю о не жадном модификаторе :(
Михай Тоадер
33
замените «если» на «время», когда ожидаете более одного случая
OneWorld
14
Имейте в виду, что matcher.find () необходим для работы этого примера кода. сбой вызова этого метода приведет к исключению «Не найдено совпадений» при вызове matcher.group (1).
Рексфорд
25
@mFontoura group (0) вернет полное совпадение с внешним ''. group (1) возвращает то, что находится между «без».
tagy22
6
@ Ларри, это поздний ответ, но? в этом случае используется модификатор non-greedy, так что this 'is' my 'data' with quotesон остановится раньше и вернется isвместо сопоставления как можно большего количества символов и возврата is' my 'data, что является поведением по умолчанию.
Timekiller
68

Вам не нужно регулярное выражение для этого.

Добавьте apache commons lang в ваш проект ( http://commons.apache.org/proper/commons-lang/ ), затем используйте:

String dataYouWant = StringUtils.substringBetween(mydata, "'");
Beothorn
источник
12
Вы должны принять во внимание, как ваше программное обеспечение будет распространяться. Если это что-то вроде веб-стартапа, не стоит добавлять Apache Commons только для того, чтобы использовать эту функциональность. Но, возможно, это не так. Кроме того, Apache Commons может предложить гораздо больше. Даже при том, что хорошо знать регулярное выражение, нужно быть осторожным, когда его использовать. Regex может быть очень трудно читать, писать и отлаживать. Учитывая некоторый контекст, использование этого может быть лучшим решением.
Beothorn
3
Иногда StringUtils уже есть, в этих случаях это решение намного чище и удобочитаемее.
Габор Надь
7
Это все равно что покупать машину, чтобы путешествовать на 5 миль (когда вы путешествуете только один раз в год).
prayagupd
Пока подстрока ищет определенную строку или значение, регулярное выражение ищет формат. Это все более динамично. Вам нужно регулярное выражение, если вы ищете шаблон вместо специального значения.
Бурахан Алкан
14
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {
    public static void main(String[] args) {
        Pattern pattern = Pattern.compile(".*'([^']*)'.*");
        String mydata = "some string with 'the data i want' inside";

        Matcher matcher = pattern.matcher(mydata);
        if(matcher.matches()) {
            System.out.println(matcher.group(1));
        }

    }
}
Шон МакЭлигот
источник
2
System.out.println (matcher.group (0)); <--- Индекс на основе нуля
nclord
4
Номер группы (0) имеет особое значение, группы захвата начинаются с индексной группы (1) (т. Е. Группа (1) является правильной в ответе). «Группы захвата индексируются слева направо, начиная с единицы. Ноль группы обозначает весь шаблон» - Источник: docs.oracle.com/javase/8/docs/api/java/util/regex/…
Apriori
12

Для этого есть простая строчка:

String target = myData.replaceAll("[^']*(?:'(.*?)')?.*", "$1");

Делая соответствующую группу необязательной, это также учитывает кавычки, не найденные, возвращая пробел в этом случае.

Смотрите живую демонстрацию .

Богемский
источник
10

Поскольку вы также отметили Scala, решение без регулярных выражений, которое легко обрабатывает несколько строк в кавычках:

val text = "some string with 'the data i want' inside 'and even more data'"
text.split("'").zipWithIndex.filter(_._2 % 2 != 0).map(_._1)

res: Array[java.lang.String] = Array(the data i want, and even more data)
Debilski
источник
4
Такое удобочитаемое решение, вот почему люди любят скала, я верю :)
praagagupd
3
Почему бы просто .split('\'').get(2)или что-то подобное в Java? Я думаю, что вам, возможно, понадобится выполнить сканирование мозга, если вы считаете, что это удобочитаемое решение - похоже, кто-то пытался сделать мне какой-нибудь код-гольф.
ArtOfWarfare
7
String dataIWant = mydata.replaceFirst(".*'(.*?)'.*", "$1");
ZehnVon12
источник
4

как в JavaScript:

mydata.match(/'([^']+)'/)[1]

фактическое регулярное выражение: /'([^']+)'/

если вы используете не жадный модификатор (как в другом посте), это так:

mydata.match(/'(.*?)'/)[1]

это чище.

Михай Тоадер
источник
2

В Скале

val ticks = "'([^']*)'".r

ticks findFirstIn mydata match {
    case Some(ticks(inside)) => println(inside)
    case _ => println("nothing")
}

for (ticks(inside) <- ticks findAllIn mydata) println(inside) // multiple matches

val Some(ticks(inside)) = ticks findFirstIn mydata // may throw exception

val ticks = ".*'([^']*)'.*".r    
val ticks(inside) = mydata // safe, shorter, only gets the first set of ticks
Даниэль С. Собрал
источник
1

Apache Commons Lang предоставляет множество вспомогательных утилит для API java.lang, прежде всего методы манипулирования строками. В вашем случае начальная и конечная подстроки одинаковы, поэтому просто вызовите следующую функцию.

StringUtils.substringBetween(String str, String tag)

Получает строку, вложенную между двумя экземплярами одной и той же строки .

Если начальная и конечная подстроки отличаются, используйте следующий перегруженный метод.

StringUtils.substringBetween(String str, String open, String close)

Получает строку, вложенную между двумя строками.

Если вы хотите, чтобы все экземпляры совпадали подстрок, то используйте,

StringUtils.substringsBetween(String str, String open, String close)

Выполняет поиск в String подстрок, разделенных начальным и конечным тегами, возвращая все соответствующие подстроки в массиве .

Для рассматриваемого примера получить все экземпляры совпадающей подстроки

String[] results = StringUtils.substringsBetween(mydata, "'", "'");
Memin
источник
0

Вы можете использовать это, я использую цикл while для хранения всех подстрок совпадений в массиве, если вы используете

if (matcher.find()) { System.out.println(matcher.group(1)); }

Вы получите подстроку совпадений, чтобы использовать ее для получения всех подстрок совпадений.

Matcher m = Pattern.compile("[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+").matcher(text);
   // Matcher  mat = pattern.matcher(text);
    ArrayList<String>matchesEmail = new ArrayList<>();
        while (m.find()){
            String s = m.group();
            if(!matchesEmail.contains(s))
                matchesEmail.add(s);
        }

    Log.d(TAG, "emails: "+matchesEmail);
Ноух Мохамед
источник
0

добавить зависимость apache.commons от вашего pom.xml

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-io</artifactId>
    <version>1.3.2</version>
</dependency>

И ниже код работает.

StringUtils.substringBetween(String mydata, String "'", String "'")
Ganesh
источник
0

Некоторые, как группа (1) не работает для меня. Я использовал группу (0), чтобы найти версию URL.

Pattern urlVersionPattern = Pattern.compile("\\/v[0-9][a-z]{0,1}\\/");
Matcher m = urlVersionPattern.matcher(url);
if (m.find()) { 
    return StringUtils.substringBetween(m.group(0), "/", "/");
}
return "v0";
Arindam
источник