¿Cómo hacer coincidir "cualquier cosa hasta esta secuencia de caracteres" en una expresión regular?

515

Tome esta expresión regular: /^[^abc]/. Esto coincidirá con cualquier carácter al principio de una cadena, excepto a, b o c.

Si agrega un *después - /^[^abc]*/, la expresión regular continuará agregando cada carácter posterior al resultado, hasta que cumpla con un a, o b , o c .

Por ejemplo, con la cadena de origen "qwerty qwerty whatever abc hello", la expresión coincidirá con "qwerty qwerty wh".

Pero, ¿y si quisiera que la cadena coincidente fuera "qwerty qwerty whatever "

... En otras palabras, ¿cómo puedo hacer coincidir todo (pero sin incluir) la secuencia exacta "abc" ?

callum
fuente
¿Qué quieres decir con match but not including?
Toto
55
Quiero decir que quiero coincidir "qwerty qwerty whatever ", sin incluir el "abc". En otras palabras, no quiero que sea la coincidencia resultante "qwerty qwerty whatever abc".
callum
2
En javascript puedes simplemente do string.split('abc')[0]. Ciertamente no es una respuesta oficial a este problema, pero lo encuentro más sencillo que la expresión regular.
Wylliam Judd

Respuestas:

1023

No especificó qué sabor de expresiones regulares está utilizando, pero esto funcionará en cualquiera de los más populares que se puedan considerar "completos".

/.+?(?=abc)/

Cómo funciona

La .+? parte es la versión no codiciosa de .+ (uno o más de cualquier cosa). Cuando usamos .+, el motor básicamente coincidirá con todo. Luego, si hay algo más en la expresión regular, retrocederá en pasos tratando de coincidir con la siguiente parte. Este es el comportamiento codicioso , lo que significa tanto como sea posible para satisfacer .

Cuando se usa .+?, en lugar de hacer coincidir todos a la vez y volver para otras condiciones (si las hay), el motor hará coincidir los siguientes caracteres paso a paso hasta que coincida la parte posterior de la expresión regular (de nuevo, si corresponde). Este es el poco codicioso , lo que significa que coincide con la menor cantidad posible de satisfacer .

/.+X/  ~ "abcXabcXabcX"        /.+/  ~ "abcXabcXabcX"
          ^^^^^^^^^^^^                  ^^^^^^^^^^^^

/.+?X/ ~ "abcXabcXabcX"        /.+?/ ~ "abcXabcXabcX"
          ^^^^                          ^

Después de eso tenemos , una afirmación de ancho cero , una mirada alrededor . Esta construcción agrupada coincide con su contenido, pero no cuenta como caracteres coincidentes ( ancho cero ). Solo regresa si es una coincidencia o no ( aserción ).(?={contents})

Por lo tanto, en otros términos, la expresión regular /.+?(?=abc)/significa:

Haga coincidir los caracteres lo menos posible hasta que se encuentre un "abc", sin contar el "abc".

sidyll
fuente
12
Esto probablemente no funcionará con saltos de línea, si se supone que deben capturarse.
einord
3
¿Cuál es la diferencia entre .+?y .*?
robbie
44
@ robbie0630 +significa 1 o más, donde *significa 0 o más. La inclusión / exclusión de la ?voluntad lo hará codicioso o no codicioso.
jinglesthula
2
@ testerjoe2 /.+?(?=abc|xyz)/
JohnWrensby
44
Me he dado cuenta de que esto no puede seleccionar nada si el patrón que estás buscando no existe; en cambio, si lo usas ^(?:(?!abc)(?!def).)*, puedes encadenar para excluir los patrones que no deseas y todavía tomará todo según sea necesario, incluso si el patrón no existe
Karan Shishoo
123

Si está buscando capturar todo hasta "abc":

/^(.*?)abc/

Explicación:

( )capturar la expresión entre paréntesis, para el acceso vía $1, $2etc.

^ inicio de línea

.*coincide con cualquier cosa, ?sin codicia (coincide con la cantidad mínima de caracteres requerida) - [1]

[1] La razón por la que esto es necesario es que, de lo contrario, en la siguiente cadena:

whatever whatever something abc something abc

de forma predeterminada, las expresiones regulares son codiciosas , lo que significa que coincidirá tanto como sea posible. Por /^.*abc/lo tanto , coincidiría con "lo que sea que sea algo por algo". Agregar el cuantificador no codicioso ?hace que la expresión regular solo coincida con "lo que sea que sea algo".

Jared Ng
fuente
44
Gracias, pero su ser hace incluya el abc en el partido. En otras palabras, la coincidencia resultante es "cualquier cosa que sea algo abc".
callum
1
¿Podrías explicar lo que en última instancia estás tratando de hacer? Si su escenario es: (A) Desea obtener todo lo que lleva a "abc", simplemente use paréntesis alrededor de lo que desea capturar. (B) Desea hacer coincidir la cadena con el "abc"; de todos modos, debe verificar el abc, por lo que debe ser parte de la expresión regular. ¿De qué otra manera puedes comprobar que está allí?
Jared Ng
sedno parece admitir coincidencias no codiciosas, ni admite mirar alrededor ( (?=...)). ¿Que más puedo hacer? Comando de ejemplo: echo "ONE: two,three, FOUR FIVE, six,seven" | sed -n -r "s/^ONE: (.+?), .*/\1/p"vuelve two,three, FOUR FIVE, pero espero two,three...
CodeManX
1
@CoDEmanX Probablemente debería publicar eso como su propia pregunta separada en lugar de un comentario, especialmente porque se trata específicamente de sed. Dicho esto, para abordar su pregunta: es posible que desee ver las respuestas a esta pregunta . También tenga en cuenta que en su ejemplo, un intérprete consciente no codicioso regresaría simplemente two, no two,three.
Jared Ng
3
Esta es la forma CADA respuesta expresión regular debe mirar - el ejemplo y explicación de todas las partes ...
jave.web
54

Como señalaron @Jared Ng y @Issun, la clave para resolver este tipo de RegEx como "hacer coincidir todo con una determinada palabra o subcadena" o "hacer coincidir todo después de una determinada palabra o subcadena" se llama aserciones de "longitud de búsqueda". . Lee más sobre ellos aquí.

En su caso particular, se puede resolver con una mirada positiva hacia el futuro: .+?(?=abc)

Una imagen vale mas que mil palabras. Vea la explicación detallada en la captura de pantalla.

Captura de pantalla de Regex101

Devy
fuente
23
.+?(?=abc)regex copiable-pastable vale más.
Tom
¿Qué pasa con la exclusión de espacios iniciales?
Royi
8

Lo que necesitas es mirar alrededor de una aserción .+? (?=abc).

Ver: Afirmaciones anticipadas y retrospectivas de longitud cero

Tenga en cuenta que [abc]no es lo mismo que abc. Dentro de los corchetes no es una cadena, cada personaje es solo una de las posibilidades. Fuera de los corchetes se convierte en la cadena.

aevanko
fuente
7

Para expresiones regulares en Java, y creo que también en la mayoría de los motores de expresiones regulares, si desea incluir la última parte, esto funcionará:

.+?(abc)

Por ejemplo, en esta línea:

I have this very nice senabctence

seleccione todos los caracteres hasta "abc" y también incluya abc

usando nuestra expresión regular, el resultado será: I have this very nice senabc

Pruebe esto: https://regex101.com/r/mX51ru/1

Dadan
fuente
4

Terminé con esta pregunta de stackoverflow después de buscar ayuda para resolver mi problema, pero no encontré ninguna solución :(

Así que tuve que improvisar ... después de un tiempo logré alcanzar la expresión regular que necesitaba:

ingrese la descripción de la imagen aquí

Como puede ver, necesitaba hasta una carpeta por delante de la carpeta "grp-bps", sin incluir el último guión. Y se requería tener al menos una carpeta después de la carpeta "grp-bps".

Editar

Versión de texto para copiar y pegar (cambie 'grp-bps' para su texto):

.*\/grp-bps\/[^\/]+
Loaderon
fuente
66
¿Sin versión de texto? 🙄
kiradotee
2

Esto tendrá sentido sobre regex.

  1. La palabra exacta se puede obtener del siguiente comando regex:

("(.*?)")/sol

Aquí, podemos obtener la palabra exacta globalmente que pertenece dentro de las comillas dobles. Por ejemplo, si nuestro texto de búsqueda es,

Este es el ejemplo de las palabras "comillas dobles"

entonces obtendremos "doble cita" de esa oración.

Ponmurugan Mohanraj
fuente
Bienvenido a StackOverflow y gracias por tu intento de ayudar. Sin embargo, me resulta difícil ver cómo esto ayuda al objetivo establecido en la pregunta. ¿Puedes elaborar? ¿Se puede aplicar a los ejemplos dados? Parece centrarse en el manejo de ", lo que para mí parece irrelevante para la pregunta.
Yunnosch
1
Hola, he explicado cómo poner la palabra u oraciones entre los caracteres especiales. Aquí nuestra pregunta también es "cualquier cosa hasta la secuencia de caracteres especiales". así que intenté con comillas dobles y lo expliqué aquí. Gracias.
Ponmurugan Mohanraj
2

En python:

.+?(?=abc) funciona para el caso de una sola línea.

[^]+?(?=abc)no funciona, ya que python no reconoce [^] como expresión regular válida. Para que la coincidencia de líneas múltiples funcione, deberá usar la opción re.DOTALL, por ejemplo:

re.findall('.+?(?=abc)', data, re.DOTALL)
David Mulder
fuente
0

Creo que necesitas subexpresiones. Si no recuerdo mal, puedes usar los ()corchetes normales para subexpresiones.

Esta parte es del manual grep:

 Back References and Subexpressions
       The back-reference \n, where n is a single digit, matches the substring
       previously matched  by  the  nth  parenthesized  subexpression  of  the
       regular expression.

Hacer algo como ^[^(abc)]debería hacer el truco.

Nandhini Anand
fuente
Lo siento, eso no funciona. Poner el abc entre paréntesis no parece hacer ninguna diferencia. Todavía se tratan como "a OR b OR c".
callum
-1

Los $marca el final de una cadena, así que algo como esto debería funcionar: [[^abc]*]$en la que están buscando algo que no terminen en cualquier iteración abc, pero tendrían que estar en el extremo

Además, si está utilizando un lenguaje de script con expresiones regulares (como php o js), tienen una función de búsqueda que se detiene cuando se encuentra por primera vez con un patrón (y puede especificar comenzar desde la izquierda o comenzar desde la derecha, o con php, puedes hacer una implosión para reflejar la cadena).

jacob
fuente
-6

prueba esto

.+?efg

Consulta :

select REGEXP_REPLACE ('abcdefghijklmn','.+?efg', '') FROM dual;

salida:

hijklmn
Balakrishna Gondesi
fuente