Pregunta Una expresión regular para hacer coincidir una subcadena que no es seguida por otra subcadena determinada


Necesito una expresión regular que coincida blahfooblah pero no blahfoobarblah

Quiero que coincida solo con foo y todo lo que rodea a foo, siempre que no esté seguido por la barra.

Intenté usar esto: foo.*(?<!bar) que está bastante cerca, pero coincide blahfoobarblah. El aspecto negativo detrás debe coincidir con cualquier cosa y no solo con la barra.

El lenguaje específico que estoy usando es Clojure que usa expresiones regulares de Java bajo el capó.

EDITAR: Más específicamente, también necesito que pase blahfooblahfoobarblah pero no blahfoobarblahblah.


75
2018-04-13 15:48


origen


Respuestas:


Tratar:

/(?!.*bar)(?=.*foo)^(\w+)$/

Pruebas:

blahfooblah            # pass
blahfooblahbarfail     # fail
somethingfoo           # pass
shouldbarfooshouldfail # fail
barfoofail             # fail

Explicación de expresión regular

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  (?!                      look ahead to see if there is not:
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    bar                      'bar'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    foo                      'foo'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  ^                        the beginning of the string
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    \w+                      word characters (a-z, A-Z, 0-9, _) (1 or
                             more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string

Otra expresión regular

Si solo quieres excluir bar cuando está directamente después foo, puedes usar

/(?!.*foobar)(?=.*foo)^(\w+)$/

Editar

Hiciste una actualización de tu pregunta para que sea específica.

/(?=.*foo(?!bar))^(\w+)$/

Nuevas pruebas

fooshouldbarpass               # pass
butnotfoobarfail               # fail
fooshouldpassevenwithfoobar    # pass
nofuuhere                      # fail

Nueva explicación

(?=.*foo(?!bar)) asegura una foo se encuentra pero no se sigue directamente bar


104
2018-04-13 15:51



Para que coincida con un foo siguiendo por algo que no comienza con bar, tratar

foo(?!bar)

Su versión con lookbehind negativo es efectivamente "coincida con foo seguido por algo que no termina en bar". Los .* coincide con todos barblah, y el (?<!bar) mira hacia atrás lah y verifica que no coincida bar, que no es así, por lo que todo el patrón coincide.


39
2018-04-13 16:00



Use una mirada negativa hacia adelante en su lugar:

\s*(?!\w*(bar)\w*)\w*(foo)\w*\s*

Esto funcionó para mí, espero que ayude. ¡Buena suerte!


2
2018-04-13 15:59



Su solicitud de coincidencia específica puede coincidir con:

\w+foo(?!bar)\w+

Esto coincidirá blahfooblahfoobarblah pero no blahfoobarblahblah.

El problema con tu expresión regular de foo.*(?<!bar) es el .* después foo. Coincide con la mayoría de los caracteres, incluidos los caracteres posteriores bar.


1
2018-04-13 16:21



Usted escribió un comentario sugiriendo que le gusta esto para trabajar haciendo coincidir todas las palabras en una cadena en lugar de la cadena entera.

En lugar de aplastar todo esto en un comentario, lo estoy publicando como una nueva respuesta.

Nueva Regex

/(?=\w*foo(?!bar))(\w+)/

Texto de ejemplo

foowithbar fooevenwithfoobar notfoobar foohere notfoobarhere perofooisokherebarforefoobarhere andnofuu needsfoo

Partidos

foowithbar fooevenwithfoobar foohere perofooisokhere bars needsfoo


1
2018-04-13 17:23