Pregunta

Sé que es posible hacer coincidir una palabra y luego revertir las coincidencias usando otras herramientas (p. ej. grep -v).Sin embargo, ¿es posible hacer coincidir líneas que no contienen una palabra específica, p. hede, usando una expresión regular?

Aporte:

hoho
hihi
haha
hede

Código:

grep "<Regex for 'doesn't contain hede'>" input

Salida deseada:

hoho
hihi
haha
¿Fue útil?

Solución

La noción de que regex no admite la coincidencia inversa no es del todo cierto. Puede imitar este comportamiento utilizando miradas negativas:

^((?!hede).)*$

La expresión regular anterior coincidirá con cualquier cadena o línea sin un salto de línea, no que contenga la (sub) cadena 'hede'. Como se mencionó, esto no es algo que regex sea & "; Bueno &"; en (o debería hacerlo), pero aún así, es posible.

Y si necesita combinar caracteres de salto de línea también, use el modificador DOT-ALL (el s final en el siguiente patrón):

/^((?!hede).)*$/s

o úselo en línea:

/(?s)^((?!hede).)*$/

(donde los /.../ son los delimitadores de expresiones regulares, es decir, no forman parte del patrón)

Si el modificador DOT-ALL no está disponible, puede imitar el mismo comportamiento con la clase de caracteres [\s\S]:

/^((?!hede)[\s\S])*$/

Explicación

Una cadena es solo una lista de n caracteres. Antes y después de cada personaje, hay una cadena vacía. Entonces, una lista de n+1 caracteres tendrá "ABhedeCD" cadenas vacías. Considere la cadena e:

    ┌──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┐
S = │e1│ A │e2│ B │e3│ h │e4│ e │e5│ d │e6│ e │e7│ C │e8│ D │e9│
    └──┴───┴──┴───┴──┴───┴──┴───┴──┴───┴──┴───┴──┴───┴──┴───┴──┘

index    0      1      2      3      4      5      6      7

donde los (?!hede). son las cadenas vacías. La expresión regular "hede" mira hacia adelante para ver si no se puede ver ninguna subcadena ., y si ese es el caso (entonces se ve algo más), entonces el ((?!hede).)* (punto) coincidirá con cualquier carácter, excepto un salto de línea . Los recorridos también se denominan aserciones de ancho cero porque no consumen ningún carácter. Solo afirman / validan algo.

Entonces, en mi ejemplo, cada cadena vacía se valida primero para ver si no hay ^((?!hede).)*$ más adelante, antes de que un carácter sea consumido por el e3 (punto). La expresión regular (?!hede) lo hará solo una vez, por lo que se envuelve en un grupo y se repite cero o más veces: <=>. Finalmente, el inicio y el final de la entrada están anclados para garantizar que se consuma toda la entrada: <=>

Como puede ver, la entrada <=> fallará porque en <=>, la expresión regular <=> falla (¡ está <=> adelante!).

Otros consejos

Tenga en cuenta que la solución a no comienza con & # 8220; hede & # 8221; :

^(?!hede).*$

generalmente es mucho más eficiente que la solución para no contiene & # 8220; hede & # 8221; :

^((?!hede).)*$

El primero verifica & # 8220; hede & # 8221; solo en la cadena de entrada & # 8217; s primera posición, en lugar de en cada posición.

Si solo lo está usando para grep, puede usar grep -v hede para obtener todas las líneas que no contienen hede.

ETA Oh, releyendo la pregunta, grep -v es probablemente lo que quisiste decir con " opciones de herramientas " ;.

Respuesta :

^((?!hede).)*$

Explicación :

^ el comienzo de la cadena, ( agrupar y capturar a \ 1 (0 o más veces (coincidiendo con la mayor cantidad posible)),
(?! mira hacia adelante para ver si no hay,

hede su cadena,

) fin de la anticipación, . cualquier carácter excepto \ n,
)* final de \ 1 (Nota: debido a que está utilizando un cuantificador en esta captura, solo la ÚLTIMA repetición del patrón capturado se almacenará en \ 1)
$ antes de un \ n opcional y el final de la cadena

Las respuestas dadas están perfectamente bien, solo un punto académico:

Expresiones regulares en el significado de las ciencias de la computación teóricas NO SON CAPAZ hazlo así. Para ellos tenía que verse así:

^([^h].*$)|(h([^e].*$|$))|(he([^h].*$|$))|(heh([^e].*$|$))|(hehe.+$) 

Esto solo hace una coincidencia COMPLETA. Hacerlo para sub-partidos sería incluso más incómodo.

Si desea que la prueba de expresiones regulares solo falle si la cadena completa coincide, lo siguiente funcionará:

^(?!hede$).*

p. - Si desea permitir todos los valores excepto & Quot; foo & Quot; (es decir, & "; foofoo &"; & "; barfoo &"; y & "; foobar &"; pasará, pero & "; foo quot; fallará), use: ^(?!foo$).*

Por supuesto, si está verificando la igualdad exacta , una mejor solución general en este caso es verificar la igualdad de la cadena, es decir

myStr !== 'foo'

Incluso podría poner la negación fuera de la prueba si necesita alguna función de expresión regular (aquí, insensibilidad a mayúsculas y minúsculas):

!/^[a-f]oo$/i.test(myStr)

La solución de expresiones regulares en la parte superior de esta respuesta puede ser útil, sin embargo, en situaciones donde se requiere una prueba de expresión regular positiva (quizás por una API).

FWIW, dado que los lenguajes regulares (también conocidos como lenguajes racionales) están cerrados bajo complementación, siempre es posible encontrar una expresión regular (también conocida como expresión racional) que niega otra expresión. Pero no muchas herramientas implementan esto.

Vcsn admite este operador (que denota {c}, postfix ).

Primero define el tipo de sus expresiones: las etiquetas son letras (lal_char) para elegir de a a z por ejemplo (definir el alfabeto cuando se trabaja con complementación es, por supuesto, muy importante), y el " valor " calculado para cada palabra es solo un booleano: true la palabra es aceptada, false, rechazada.

En Python:

In [5]: import vcsn
        c = vcsn.context('lal_char(a-z), b')
        c
Out[5]: {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z} → 𝔹

luego ingresa su expresión:

In [6]: e = c.expression('(hede){c}'); e
Out[6]: (hede)^c

convierte esta expresión a un autómata:

In [7]: a = e.automaton(); a

 El autómata correspondiente

finalmente, convierta este autómata a una expresión simple.

In [8]: print(a.expression())
        \e+h(\e+e(\e+d))+([^h]+h([^e]+e([^d]+d([^e]+e[^]))))[^]*

donde + generalmente se denota |, \e denota la palabra vacía y [^] generalmente se escribe . (cualquier carácter). Entonces, con un poco de reescritura ()|h(ed?)?|([^h]|h([^e]|e([^d]|d([^e]|e.)))).*.

Puede ver este ejemplo aquí , y pruebe Vcsn en línea allí .

Aquí una buena explicación de por qué no es fácil negar una expresión regular arbitraria. Sin embargo, tengo que estar de acuerdo con las otras respuestas: si esto no es una pregunta hipotética, entonces una expresión regular no es la opción correcta aquí.

Con anticipación negativa, la expresión regular puede coincidir con algo que no contiene un patrón específico. Esto es respondido y explicado por Bart Kiers. ¡Gran explicación!

Sin embargo, con la respuesta de Bart Kiers, la parte de anticipación probará de 1 a 4 caracteres por delante, mientras que coincide con cualquier carácter individual. Podemos evitar esto y dejar que la parte anticipada revise todo el texto, asegúrese de que no haya 'hede', y luego la parte normal (. *) Puede comer todo el texto al mismo tiempo.

Aquí está la expresión regular mejorada:

/^(?!.*?hede).*$/

Tenga en cuenta que el cuantificador perezoso (*?) en la parte de búsqueda anticipada negativa es opcional, puede usar el cuantificador codicioso (*) en su lugar, dependiendo de sus datos: si 'hede' se presenta y en la mitad inicial del texto, el cuantificador perezoso puede ser más rápido; de lo contrario, el cuantificador codicioso será más rápido. Sin embargo, si 'hede' no se presenta, ambos serían igual de lentos.

Aquí está el código de demostración .

Para obtener más información sobre lookahead, consulte el excelente artículo: Dominar Lookahead y Lookbehind .

Además, consulte RegexGen.js , un generador de expresiones regulares de JavaScript que ayuda a construir expresiones regulares complejas. Con RegexGen.js, puede construir la expresión regular de una manera más legible:

var _ = regexGen;

var regex = _(
    _.startOfLine(),             
    _.anything().notContains(       // match anything that not contains:
        _.anything().lazy(), 'hede' //   zero or more chars that followed by 'hede',
                                    //   i.e., anything contains 'hede'
    ), 
    _.endOfLine()
);

Puntos de referencia

Decidí evaluar algunas de las Opciones presentadas y comparar su rendimiento, así como usar algunas Características nuevas. Evaluación comparativa en .NET Regex Engine: http://regexhero.net/tester/

Texto de referencia:

¡Las primeras 7 líneas no deberían coincidir, ya que contienen la Expresión buscada, mientras que las 7 líneas inferiores deberían coincidir!

Regex Hero is a real-time online Silverlight Regular Expression Tester.
XRegex Hero is a real-time online Silverlight Regular Expression Tester.
Regex HeroRegex HeroRegex HeroRegex HeroRegex Hero is a real-time online Silverlight Regular Expression Tester.
Regex Her Regex Her Regex Her Regex Her Regex Her Regex Her Regex Hero is a real-time online Silverlight Regular Expression Tester.
Regex Her is a real-time online Silverlight Regular Expression Tester.Regex Hero
egex Hero egex Hero egex Hero egex Hero egex Hero egex Hero Regex Hero is a real-time online Silverlight Regular Expression Tester.
RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRegex Hero is a real-time online Silverlight Regular Expression Tester.

Regex Her
egex Hero
egex Hero is a real-time online Silverlight Regular Expression Tester.
Regex Her is a real-time online Silverlight Regular Expression Tester.
Regex Her Regex Her Regex Her Regex Her Regex Her Regex Her is a real-time online Silverlight Regular Expression Tester.
Nobody is a real-time online Silverlight Regular Expression Tester.
Regex Her o egex Hero Regex  Hero Reg ex Hero is a real-time online Silverlight Regular Expression Tester.

Resultados:

Los resultados son iteraciones por segundo como la mediana de 3 ejecuciones - Número más grande = Mejor

01: ^((?!Regex Hero).)*$                    3.914   // Accepted Answer
02: ^(?:(?!Regex Hero).)*$                  5.034   // With Non-Capturing group
03: ^(?>[^R]+|R(?!egex Hero))*$             6.137   // Lookahead only on the right first letter
04: ^(?>(?:.*?Regex Hero)?)^.*$             7.426   // Match the word and check if you're still at linestart
05: ^(?(?=.*?Regex Hero)(?#fail)|.*)$       7.371   // Logic Branch: Find Regex Hero? match nothing, else anything

P1: ^(?(?=.*?Regex Hero)(*FAIL)|(*ACCEPT))  ?????   // Logic Branch in Perl - Quick FAIL
P2: .*?Regex Hero(*COMMIT)(*FAIL)|(*ACCEPT) ?????   // Direct COMMIT & FAIL in Perl

Dado que .NET no admite verbos de acción (* FAIL, etc.) no pude probar las soluciones P1 y P2.

Resumen:

Traté de probar la mayoría de las soluciones propuestas, algunas optimizaciones son posibles para ciertas palabras. Por ejemplo, si las dos primeras letras de la cadena de búsqueda no son iguales, la respuesta 03 se puede expandir a ^(?>[^R]+|R+(?!egex Hero))*$ resultando en una pequeña ganancia de rendimiento.

Pero la solución más rápida en general, más legible y en cuanto al rendimiento parece ser 05 usando una declaración condicional o 04 con el cuantificador posesivo. Creo que las soluciones de Perl deberían ser aún más rápidas y más fáciles de leer.

No regex, pero he encontrado lógico y útil usar greps seriales con tubería para eliminar el ruido.

ej. buscar un archivo de configuración de apache sin todos los comentarios-

grep -v '\#' /opt/lampp/etc/httpd.conf      # this gives all the non-comment lines

y

grep -v '\#' /opt/lampp/etc/httpd.conf |  grep -i dir

La lógica de los greps en serie es (no es un comentario) y (coincide con el directorio)

con esto, evitas probar con anticipación en cada posición:

/^(?:[^h]+|h++(?!ede))*+$/

equivalente a (para .net):

^(?>(?:[^h]+|h+(?!ede))*)$

Antigua respuesta:

/^(?>[^h]+|h+(?!ede))*$/

Lo mencionado anteriormente (?:(?!hede).)* es excelente porque se puede anclar.

^(?:(?!hede).)*$               # A line without hede

foo(?:(?!hede).)*bar           # foo followed by bar, without hede between them

Pero lo siguiente sería suficiente en este caso:

^(?!.*hede)                    # A line without hede

Esta simplificación está lista para tener " AND " cláusulas agregadas:

^(?!.*hede)(?=.*foo)(?=.*bar)   # A line with foo and bar, but without hede
^(?!.*hede)(?=.*foo).*bar       # Same

Así es como lo haría:

^[^h]*(h(?!ede)[^h]*)*$

Preciso y más eficiente que las otras respuestas. Implementa la técnica de eficiencia & Quot; desenrollando el ciclo & Quot; de Friedl y requiere mucho menos retroceso.

Si desea hacer coincidir un carácter para negar una palabra similar a negar clase de caracteres:

Por ejemplo, una cadena:

<?
$str="aaa        bbb4      aaa     bbb7";
?>

No usar:

<?
preg_match('/aaa[^bbb]+?bbb7/s', $str, $matches);
?>

Uso:

<?
preg_match('/aaa(?:(?!bbb).)+?bbb7/s', $str, $matches);
?>

Aviso "(?!bbb)." no es mirar hacia atrás ni mirar hacia adelante, es actual, por ejemplo:

"(?=abc)abcde", "(?!abc)abcde"

El OP no especificó o Tag la publicación para indicar el contexto (lenguaje de programación, editor, herramienta) en el que se utilizará Regex.

Para mí, a veces necesito hacer esto mientras edito un archivo usando Textpad .

hede admite algunas expresiones regulares, pero no admite mirar hacia adelante o hacia atrás, por lo que se requieren algunos pasos.

Si estoy buscando retener todas las líneas que NO contienen la cadena <=> , lo haría así:

  

1. Busque / reemplace todo el archivo para agregar un & Quot; Tag & Quot; al comienzo de cada línea que contiene cualquier texto.

    Search string:^(.)  
    Replace string:<@#-unique-#@>\1  
    Replace-all  
  

2. Elimine todas las líneas que contienen la cadena <=> (la cadena de reemplazo está vacía):

    Search string:<@#-unique-#@>.*hede.*\n  
    Replace string:<nothing>  
    Replace-all  

  

3. En este punto, todas las líneas restantes NO contienen la cadena <=> . Elimine la única & Quot; Etiqueta & Quot; de todas las líneas (la cadena de reemplazo está vacía):

    Search string:<@#-unique-#@>
    Replace string:<nothing>  
    Replace-all  

Ahora tiene el texto original con todas las líneas que contienen la cadena <=> eliminada.


Si estoy buscando Hacer algo más con solo líneas que NO contengan la cadena <=> , lo haría así:

  

1. Busque / reemplace todo el archivo para agregar un & Quot; Tag & Quot; al comienzo de cada línea que contiene cualquier texto.

    Search string:<@#-unique-#@>(.*hede)
    Replace string:\1  
    Replace-all  
  

2. Para todas las líneas que contienen la cadena <=> , elimine la única & Quot; Etiqueta & Quot ;:

<*>

  

3. En este punto, todas las líneas que comienzan con & Quot; Tag & Quot ;, NO contienen la cadena <=> . Ahora puedo hacer mi Algo más solo con esas líneas.

  

4. Cuando termine, elimino el & Quot; Tag & Quot; de todas las líneas (la cadena de reemplazo está vacía):

<*>

Una, en mi opinión, una variante más legible de la respuesta principal:

^(?!.*hede)

Básicamente, " coincida al comienzo de la línea si y solo si no tiene 'hede' en ella " - por lo que el requisito se tradujo casi directamente en expresiones regulares.

Por supuesto, es posible tener múltiples requisitos de falla:

^(?!.*(hede|hodo|hada))

Detalles: El ancla ^ asegura que el motor de expresiones regulares no vuelva a intentar la coincidencia en cada ubicación de la cadena, que coincidiría con cada cadena.

El ancla ^ en el principio está destinado a representar el comienzo de la línea. La herramienta grep coincide con cada línea de una en una, en contextos en los que está trabajando con una cadena multilínea, puede usar & Quot; m & Quot; bandera:

/^(?!.*hede)/m # JavaScript syntax

o

(?m)^(?!.*hede) # Inline flag

Desde la introducción de ruby-2.4.1, podemos usar el nuevo Operador ausente en Ruby & # 8217; s Expresiones regulares

del oficial doc

(?~abc) matches: "", "ab", "aab", "cccc", etc.
It doesn't match: "abc", "aabc", "ccccabc", etc.

Por lo tanto, en su caso ^(?~hede)$ hace el trabajo por usted

2.4.1 :016 > ["hoho", "hihi", "haha", "hede"].select{|s| /^(?~hede)$/.match(s)}
 => ["hoho", "hihi", "haha"]

A través del verbo PCRE (*SKIP)(*F)

^hede$(*SKIP)(*F)|^.*$

Esto omitiría por completo la línea que contiene la cadena exacta. hede y coincide con todas las líneas restantes.

MANIFESTACIÓN

Ejecución de las piezas:

Consideremos la expresión regular anterior dividiéndola en dos partes.

  1. parte antes del | símbolo.Parte no debe coincidir.

    ^hede$(*SKIP)(*F)
    
  2. Parte después de la | símbolo.Parte debe ser coincidente.

    ^.*$
    

PARTE 1

El motor Regex comenzará su ejecución desde la primera parte.

^hede$(*SKIP)(*F)

Explicación:

  • ^ Afirma que estamos al principio.
  • hede Coincide con la cuerda hede
  • $ Afirma que estamos al final de la línea.

Entonces la línea que contiene la cadena hede estaría emparejado.Una vez que el motor de expresiones regulares ve lo siguiente (*SKIP)(*F) (Nota:podrías escribir (*F) como (*FAIL)) verbo, se salta y hace que la coincidencia falle. | llamado alteración u operador lógico OR agregado junto al verbo PCRE que a su vez coincide con todos los límites existentes entre todos y cada uno de los caracteres en todas las líneas, excepto que la línea contiene la cadena exacta hede.Ver la demostración aquí.Es decir, intenta hacer coincidir los caracteres de la cadena restante.Ahora se ejecutaría la expresión regular de la segunda parte.

PARTE 2

^.*$

Explicación:

  • ^ Afirma que estamos al principio.es decir, coincide con todos los inicios de línea excepto el del hede línea.Ver la demostración aquí.
  • .* En el modo multilínea, . coincidiría con cualquier carácter excepto los de nueva línea o retorno de carro.Y * repetiría el carácter anterior cero o más veces.Entonces .* coincidiría con toda la línea.Ver la demostración aquí.

    Oye, ¿por qué agregaste .* en lugar de .+?

    Porque .* coincidiría con una línea en blanco pero .+ no coincidirá con un espacio en blanco.Queremos hacer coincidir todas las líneas excepto hede , también puede haber líneas en blanco en la entrada .entonces debes usar .* en lugar de .+ . .+ repetiría el carácter anterior una o más veces.Ver .* coincide con una línea en blanco aquí.

  • $ Aquí no es necesario el anclaje de final de línea.

Como nadie más ha dado una respuesta directa a la pregunta eso fue preguntado, Lo haré.

La respuesta es que con POSIX grep, es imposible satisfacer literalmente esta solicitud:

grep "Regex for doesn't contain hede" Input

La razón es que POSIX grep sólo se requiere trabajar con Expresiones regulares básicas, que simplemente no son lo suficientemente potentes para realizar esa tarea (no son capaces de analizar lenguajes regulares debido a la falta de alternancia y agrupación).

Sin embargo, GNU grep implementa extensiones que lo permiten.En particular, \| es el operador de alternancia en la implementación de BRE de GNU, y \( y \) son los operadores de agrupación.Si su motor de expresiones regulares admite alternancia, expresiones entre corchetes negativos, agrupación y la estrella Kleene, y es capaz de anclarse al principio y al final de la cadena, eso es todo lo que necesita para este enfoque.

Con GNU grep, sería algo como:

grep "^\([^h]\|h\(h\|eh\|edh\)*\([^eh]\|e[^dh]\|ed[^eh]\)\)*\(\|h\(h\|eh\|edh\)*\(\|e\|ed\)\)$" Input

(encontrado con Grial y algunas optimizaciones adicionales hechas a mano).

También puedes utilizar una herramienta que implemente Expresiones regulares extendidas, como egrep, para deshacerse de las barras invertidas:

egrep "^([^h]|h(h|eh|edh)*([^eh]|e[^dh]|ed[^eh]))*(|h(h|eh|edh)*(|e|ed))$" Input

Aquí hay un script para probarlo (tenga en cuenta que genera un archivo testinput.txt en el directorio actual):

#!/bin/bash
REGEX="^\([^h]\|h\(h\|eh\|edh\)*\([^eh]\|e[^dh]\|ed[^eh]\)\)*\(\|h\(h\|eh\|edh\)*\(\|e\|ed\)\)$"

# First four lines as in OP's testcase.
cat > testinput.txt <<EOF
hoho
hihi
haha
hede

h
he
ah
head
ahead
ahed
aheda
ahede
hhede
hehede
hedhede
hehehehehehedehehe
hedecidedthat
EOF
diff -s -u <(grep -v hede testinput.txt) <(grep "$REGEX" testinput.txt)

En mi sistema imprime:

Files /dev/fd/63 and /dev/fd/62 are identical

como se esperaba.

Para aquellos interesados ​​en los detalles, la técnica empleada es convertir la expresión regular que coincide con la palabra en un autómata finito, luego invertir el autómata cambiando cada estado de aceptación a no aceptación y viceversa, y luego convertir el FA resultante nuevamente a una expresión regular.

Finalmente, como todos han notado, si su motor de expresiones regulares admite una anticipación negativa, eso simplifica mucho la tarea.Por ejemplo, con GNU grep:

grep -P '^((?!hede).)*$' Input

Actualizar: Recientemente he descubierto que Kendall Hopkins es excelente. Teoría formal biblioteca, escrita en PHP, que proporciona una funcionalidad similar a Grail.Al usarlo, y a un simplificador escrito por mí mismo, pude escribir un generador en línea de expresiones regulares negativas dada una frase de entrada (actualmente solo se admiten caracteres alfanuméricos y de espacio): http://www.formauri.es/personal/pgimeno/misc/non-match-regex/

Para hede produce:

^([^h]|h(h|e(h|dh))*([^eh]|e([^dh]|d[^eh])))*(h(h|e(h|dh))*(ed?)?)?$

que es equivalente a lo anterior.

Puede ser más fácil de mantener dos expresiones regulares en su código, una para hacer la primera coincidencia y luego, si coincide, ejecutar la segunda expresión regular para verificar si hay casos atípicos que desea bloquear, por ejemplo. ^.*(hede).* entonces tenga la lógica apropiada en su código.

Bien, admito que esto no es realmente una respuesta a la pregunta publicada y también puede utilizar un poco más de procesamiento que una sola expresión regular.Pero para los desarrolladores que vinieron aquí buscando una solución de emergencia rápida para un caso atípico, esta solución no debe pasarse por alto.

El Idioma TXR admite la negación de expresiones regulares.

$ txr -c '@(repeat)
@{nothede /~hede/}
@(do (put-line nothede))
@(end)'  Input

Un ejemplo más complicado:coincide con todas las líneas que comienzan con a y terminar con z, pero no contiene la subcadena hede:

$ txr -c '@(repeat)
@{nothede /a.*z&~.*hede.*/}
@(do (put-line nothede))
@(end)' -
az         <- echoed
az
abcz       <- echoed
abcz
abhederz   <- not echoed; contains hede
ahedez     <- not echoed; contains hede
ace        <- not echoed; does not end in z
ahedz      <- echoed
ahedz

La negación de expresiones regulares no es particularmente útil por sí sola, pero cuando también tienes una intersección, las cosas se ponen interesantes, ya que tienes un conjunto completo de operaciones booleanas:se puede expresar "el conjunto que coincide con esto, excepto las cosas que coinciden con aquello".

La siguiente función lo ayudará a obtener el resultado deseado

<?PHP
      function removePrepositions($text){

            $propositions=array('/\bfor\b/i','/\bthe\b/i'); 

            if( count($propositions) > 0 ) {
                foreach($propositions as $exceptionPhrase) {
                    $text = preg_replace($exceptionPhrase, '', trim($text));

                }
            $retval = trim($text);

            }
        return $retval;
    }


?>

Cómo usar los verbos de control de retroceso de PCRE para que coincidan con una línea que no contiene una palabra

Aquí hay un método que no he visto usado antes:

/.*hede(*COMMIT)^|/

Cómo funciona

Primero, trata de encontrar " hede " en algún lugar de la línea Si tiene éxito, en este punto, (*COMMIT) le dice al motor que no solo retroceda en caso de falla, sino que no intente ninguna otra coincidencia en ese caso. Luego, intentamos hacer coincidir algo que no puede coincidir (en este caso, ^).

Si una línea no contiene " hede " entonces la segunda alternativa, un subpatrón vacío, coincide con éxito con la cadena de asunto.

Este método no es más eficiente que una anticipación negativa, pero pensé que simplemente lo lanzaría aquí en caso de que alguien lo encuentre ingenioso y lo use para otras aplicaciones más interesantes.

Tal vez encuentres esto en Google mientras intentas escribir una expresión regular que pueda hacer coincidir segmentos de una línea (a diferencia de líneas enteras) que sí lo hacen. no contener una subcadena.Me tomó un tiempo darme cuenta, así que lo compartiré:

Dada una cadena: <span class="good">bar</span><span class="bad">foo</span><span class="ugly">baz</span>

quiero igualar <span> etiquetas que no contienen la subcadena "mala".

/<span(?:(?!bad).)*?> coincidirá <span class=\"good\"> y <span class=\"ugly\">.

Observe que hay dos conjuntos (capas) de paréntesis:

  • El más interno es para la anticipación negativa (no es un grupo de captura)
  • Ruby interpretó el más externo como grupo de captura, pero no queremos que sea un grupo de captura, así que agregué?:al principio y ya no se interpreta como un grupo de captura.

Demostración en Rubí:

s = '<span class="good">bar</span><span class="bad">foo</span><span class="ugly">baz</span>'
s.scan(/<span(?:(?!bad).)*?>/)
# => ["<span class=\"good\">", "<span class=\"ugly\">"]

Una solución más simple es usar el operador no !

Su if declaración deberá coincidir con " contiene " y no coincide con " excluye " ;.

var contains = /abc/;
var excludes =/hede/;

if(string.match(contains) && !(string.match(excludes))){  //proceed...

Creo que los diseñadores de RegEx anticiparon el uso de no operadores.

Con ConyEdit , puede usar la línea de comando cc.gl !/hede/ para obtener líneas que no contienen la expresión regular coincidencia, o utilice la línea de comando cc.dl /hede/ para eliminar líneas que contienen la coincidencia de expresiones regulares. Tienen el mismo resultado.

^ ((?! hede).) * $ es una solución elegante, excepto porque consume caracteres que no podrá combinar con otros criterios. Por ejemplo, supongamos que desea verificar la no presencia de & Quot; hede & Quot; y la presencia de & "; jaja. &"; Esta solución funcionaría porque no consumirá caracteres:

^ (?!. \ bhede \ b) (? =. \ bhaha \ b)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top