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

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

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, "'");

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

    }
}

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 .


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)

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

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.


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


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, "'", "'");

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

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 "'")

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";
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.