Como extrair uma substring usando regex


382

Eu tenho uma string que tem duas aspas simples, o 'caractere. Entre as aspas simples estão os dados que desejo.

Como posso escrever um regex para extrair "os dados que eu quero" do texto a seguir?

mydata = "some string with 'the data i want' inside";

Respostas:


569

Supondo que você queira a parte entre aspas simples, use esta expressão regular com um Matcher:

"'(.*?)'"

Exemplo:

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));
}

Resultado:

os dados que eu quero

12
caramba .. eu sempre esqueço o modificador não ganancioso :(
Mihai Toader

33
substitua o "se" por um "enquanto" quando você espera mais de uma ocorrência
OneWorld

14
lembre-se de que matcher.find () é necessário para que esse exemplo de código funcione. não chamar este método resultará em uma exceção "Nenhuma correspondência encontrada" quando o matcher.group (1) for chamado.
Rexford

25
O grupo @mFontoura (0) retornaria a correspondência completa com o externo ''. O grupo (1) retorna o que está entre o '' sem o '' em si.
tagy22

6
@ Larry esta é uma resposta tardia, mas? nesse caso, é um modificador não ganancioso, de modo que this 'is' my 'data' with quotesparava mais cedo e retornava, em isvez de corresponder ao máximo de caracteres possível e retornava is' my 'data, que é o comportamento padrão.
Timekiller 12/09/16

68

Você não precisa de regex para isso.

Adicione o apache commons lang ao seu projeto ( http://commons.apache.org/proper/commons-lang/ ) e use:

String dataYouWant = StringUtils.substringBetween(mydata, "'");

12
Você precisa levar em consideração como o seu software será distribuído. Se for algo como um webstart, não é aconselhável adicionar o Apache commons apenas para usar essa funcionalidade. Mas talvez não seja. Além do Apache commons, tem muito mais a oferecer. Por mais difícil que seja bom conhecer regex, você deve ter cuidado ao usá-lo. Regex pode ser realmente difícil de ler, escrever e depurar. Dado algum contexto usando isso, poderia ser a melhor solução.
Beothorn

3
Às vezes, o StringUtils já está lá; nesses casos, essa solução é muito mais limpa e legível.
Gábor Nagy

7
É como comprar um carro para viajar 5 milhas (quando você viaja apenas uma vez por ano).
precisa saber é

Enquanto a substring procura uma sequência ou valor específico, a regex procura um formato. É cada vez mais dinâmico. Você precisa de regex, se estiver procurando um padrão em vez de um valor especial.
burakhan alcan

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)); <--- Índice baseado em zero
nclord 13/05

4
Não. O grupo (0) tem um significado especial, os grupos de captura começam no grupo de índices (1) (ou seja, o grupo (1) está correto na resposta). "Os grupos de captura são indexados da esquerda para a direita, iniciando em um. O grupo zero indica o padrão inteiro" - Fonte: docs.oracle.com/javase/8/docs/api/java/util/regex/…
Apriori

12

Existe uma linha simples para isso:

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

Ao tornar o grupo correspondente opcional, isso também serve para cotações não encontradas retornando um espaço em branco nesse caso.

Veja demonstração ao vivo .


10

Como você também marcou o Scala, uma solução sem regex que lida facilmente com várias seqüências de caracteres citadas:

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)

4
Então solução legível, é por isso que as pessoas gostam scala I Belive :)
prayagupd

3
Por que não apenas .split('\'').get(2)ou algo nesse sentido em Java? Acho que você pode precisar fazer uma varredura cerebral se achar que é uma solução legível - parece que alguém estava tentando fazer algum código de golfe para mim.
ArtOfWarfare

7
String dataIWant = mydata.replaceFirst(".*'(.*?)'.*", "$1");

4

como em javascript:

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

o regexp real é: /'([^']+)'/

se você usar o modificador não guloso (como em outro post), é assim:

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

é mais limpo.


2

Em Scala,

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

O Apache Commons Lang fornece vários utilitários auxiliares para a API java.lang, principalmente os métodos de manipulação de String. No seu caso, as substrings inicial e final são as mesmas, então chame a seguinte função.

StringUtils.substringBetween(String str, String tag)

Obtém a String aninhada entre duas instâncias da mesma String .

Se as substrings inicial e final forem diferentes, use o seguinte método sobrecarregado.

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

Obtém a String aninhada entre duas Strings.

Se você deseja todas as instâncias das substrings correspondentes, use,

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

Procura em String por substrings delimitados por uma tag de início e fim, retornando todas as substrings correspondentes em uma matriz .

Para o exemplo em questão, obter todas as instâncias da substring correspondente

String[] results = StringUtils.substringsBetween(mydata, "'", "'");

0

você pode usar isso eu uso while loop para armazenar todas as correspondências de substring na matriz, se você usar

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

você obterá a correspondência de substring para poder usá-lo para obter todas as correspondências de substring

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

adicionar dependência apache.commons ao seu pom.xml

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

E o código abaixo funciona.

StringUtils.substringBetween(String mydata, String "'", String "'")

0

De alguma forma, como o grupo (1) não funcionou para mim. Eu usei o grupo (0) para encontrar a versão do 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";
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.