Cómo extraer una subcadena usando regex

382

Tengo una cadena que tiene dos comillas simples, el 'personaje. Entre las comillas simples están los datos que quiero.

¿Cómo puedo escribir una expresión regular para extraer "los datos que quiero" del siguiente texto?

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

Respuestas:

569

Suponiendo que desea la parte entre comillas simples, use esta expresión regular con un Matcher:

"'(.*?)'"

Ejemplo:

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:

los datos que quiero
Mark Byers
fuente
12
maldición ... siempre me olvido del modificador no codicioso :(
Mihai Toader
33
reemplace el "if" con un "while" cuando espere más de una ocurrencia
OneWorld
14
tenga en cuenta que matcher.find () es necesario para que este código de muestra funcione. no llamar a este método dará como resultado una excepción "No se encontró coincidencia" cuando se llama a matcher.group (1).
rexford
25
@mFontoura group (0) devolvería la coincidencia completa con el exterior ''. group (1) devuelve lo que está entre '' sin los '' mismos.
tagy22
66
@ Larry esta es una respuesta tardía, pero? en este caso es un modificador no codicioso, por lo que this 'is' my 'data' with quotesse detendría antes y volvería en islugar de hacer coincidir tantos caracteres como sea posible y regresar is' my 'data, que es el comportamiento predeterminado.
Timekiller
68

No necesitas expresiones regulares para esto.

Agregue apache commons lang a su proyecto ( http://commons.apache.org/proper/commons-lang/ ), luego use:

String dataYouWant = StringUtils.substringBetween(mydata, "'");
Beothorn
fuente
12
Debe tener en cuenta cómo se distribuirá su software. Si es algo así como un inicio web, no es aconsejable agregar recursos comunes de Apache solo para usar esta funcionalidad. Pero tal vez no lo es. Además, Apache commons tiene mucho más que ofrecer. Incluso si es bueno saber regex, debes tener cuidado de cuándo usarlo. Regex puede ser realmente difícil de leer, escribir y depurar. Dado algún contexto, usar esto podría ser la mejor solución.
Beothorn
3
A veces StringUtils ya está allí, en esos casos esta solución es mucho más limpia y legible.
Gábor Nagy
77
Es como comprar un automóvil para viajar 5 millas (cuando viaja solo una vez al año).
prayagupd 01 de
Mientras que la subcadena busca una cadena o valor específico, la expresión regular busca un formato. Es cada vez más dinámico. Necesita expresiones regulares, si está buscando un patrón en lugar de un valor especial.
burakhan alkan
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
fuente
2
System.out.println (matcher.group (0)); <--- Índice basado en cero
nclord
44
No. el grupo (0) tiene un significado especial, los grupos de captura comienzan en el grupo índice (1) (es decir, el grupo (1) es correcto en la respuesta). "Grupos de captura se indexan de izquierda a derecha, comenzando en un grupo de cero indica el patrón completo." - Fuente: docs.oracle.com/javase/8/docs/api/java/util/regex/...
A priori
12

Hay una frase simple para esto:

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

Al hacer que el grupo coincidente sea opcional, esto también atiende las citas que no se encuentran al devolver un espacio en blanco en ese caso.

Ver demostración en vivo .

Bohemio
fuente
10

Debido a que también seleccionó Scala, una solución sin expresiones regulares que se ocupa fácilmente de múltiples cadenas entre comillas:

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
fuente
44
Solución tan legible, es por eso que la gente ama scala, creo :)
prayagupd
3
¿Por qué no solo .split('\'').get(2)o algo así en Java? Creo que es posible que deba hacerse un escáner cerebral si cree que es una solución legible: parece que alguien estaba tratando de hacerme un código de golf.
ArtOfWarfare
7
String dataIWant = mydata.replaceFirst(".*'(.*?)'.*", "$1");
ZehnVon12
fuente
4

como en javascript:

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

La expresión regular real es: /'([^']+)'/

si usa el modificador no codicioso (según otra publicación) es así:

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

Está más limpio.

Mihai Toader
fuente
2

En 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
fuente
1

Apache Commons Lang proporciona una gran cantidad de utilidades auxiliares para la API java.lang, especialmente los métodos de manipulación de cadenas. En su caso, las subcadenas de inicio y finalización son las mismas, así que simplemente llame a la siguiente función.

StringUtils.substringBetween(String str, String tag)

Obtiene la cadena que está anidada entre dos instancias de la misma cadena .

Si las subcadenas de inicio y fin son diferentes, utilice el siguiente método sobrecargado.

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

Obtiene la cadena anidada entre dos cadenas.

Si desea todas las instancias de las subcadenas coincidentes, use,

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

Busca en una cadena las subcadenas delimitadas por una etiqueta de inicio y fin, devolviendo todas las subcadenas coincidentes en una matriz .

Para el ejemplo en cuestión, obtener todas las instancias de la subcadena coincidente

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

puede usar esto que uso mientras que el bucle para almacenar todas las subcadenas coincidentes en la matriz si usa

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

obtendrá subcadenas de coincidencias para que pueda usar esto para obtener todas las subcadenas de coincidencias

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
fuente
0

agregue la dependencia apache.commons en su pom.xml

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

Y debajo del código funciona.

StringUtils.substringBetween(String mydata, String "'", String "'")
Ganesh
fuente
0

De alguna manera, el grupo (1) no funcionó para mí. Usé el grupo (0) para encontrar la versión de la 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
fuente