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";
asdasd
fonte

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
Mark Byers
fonte
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, "'");
Beothorn
fonte
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));
        }

    }
}
Sean McEligot
fonte
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 .

Boêmio
fonte
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)
Debilski
fonte
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");
ZehnVon12
fonte
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.

Mihai Toader
fonte
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
Daniel C. Sobral
fonte
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, "'", "'");
Memin
fonte
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);
Nouh Mohamed
fonte
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 "'")
Ganesh
fonte
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";
Arindam
fonte