Expresión regular para que coincida con una línea que no contiene una palabra?

Sé que es posible hacer coincidir una palabra y luego invertir las coincidencias con otras herramientas (por ejemplo, grep -v ). Sin embargo, me gustaría saber si es posible hacer coincidir las líneas que no contienen una palabra específica (por ejemplo, hede) con una expresión regular.

Entrada:

 hoho hihi haha hede 

Código:

 grep "" input 

Salida deseada:

 hoho hihi haha 

La noción de que Regex no es compatible con 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, que no contenga la (sub) cadena ‘hede’. Como se mencionó, esto no es algo que regex es “bueno” en (o debería), pero aún así, es posible.

Y si también necesita hacer coincidir los caracteres line break chars, use el modificador DOT-ALL (los siguientes en el siguiente patrón):

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

o usarlo en línea:

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

(donde /.../ son los delimitadores de expresiones regulares, es decir, que 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 caracteres tendrá n+1 cadenas vacías. Considere la cadena "ABhedeCD" :

  ┌──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┐ 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 las e son las cuerdas vacías. La expresión regular (?!hede). mira hacia adelante para ver si no hay ninguna subcadena "hede" para ser vista, y si ese es el caso (entonces se ve algo más), entonces el . (punto) coincidirá con cualquier carácter excepto un salto de línea. Las búsquedas se llaman también aseriones de ancho cero porque no consumen ningún carácter. Solo afirman / validan algo.

Entonces, en mi ejemplo, cada cadena vacía primero se valida para ver si no hay "hede" adelante, antes de que un personaje sea consumido por . (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: ((?!hede).)* . Finalmente, el inicio y el final de la entrada se anclan para asegurarse de que se consume toda la entrada: ^((?!hede).)*$

Como puede ver, la entrada "ABhedeCD" fallará porque en e3 , la expresión regular (?!hede) falla (¡hay "hede" adelante!).

Tenga en cuenta que la solución a no comienza con “hede” :

 ^(?!hede).*$ 

generalmente es mucho más eficiente que la solución para no contiene “hede” :

 ^((?!hede).)*$ 

El primero busca “hede” solo en la primera posición de la cadena de entrada, 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 contengan hede.

ETA Oh, volviendo a leer la pregunta, grep -v es probablemente lo que quisiste decir con “opciones de herramientas”.

Responder:

 ^((?!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 cuerda,

) fin de mirar hacia adelante,. cualquier caracter excepto \ n,
)* end of \ 1 (Nota: como 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:

Las expresiones regulares en el significado de las ciencias de la computación teórica NO PUEDEN hacerlo así. Para ellos tenía que parecerse a esto:

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

Esto solo hace un partido COMPLETO. Hacerlo para sub-matches sería incluso más incómodo.

Si desea que la prueba de expresión regular solo falle si toda la cadena coincide, lo siguiente funcionará:

 ^(?!hede$).* 

por ejemplo, si desea permitir todos los valores excepto “foo” (es decir, “foofoo”, “barfoo” y “foobar” pasarán, pero “foo” fallará), use: ^(?!foo$).*

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

 myStr !== 'foo' 

Incluso podría poner la negación fuera de la prueba si necesita alguna característica de expresiones regulares (aquí, insensibilidad de mayúsculas y minúsculas):

 !/^[af]oo$/i.test(myStr) 

La solución de expresiones regulares en la parte superior puede ser útil, sin embargo, en situaciones donde se requiere una prueba de expresiones regulares positiva (tal vez por una API).

Aquí hay 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 más que una pregunta hipotética, entonces una expresión regular no es la elección correcta aquí.

FWIW, dado que los lenguajes regulares (también conocidos como idiomas racionales) se cierran bajo la 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 tags son letter ( lal_char ) para elegir de la a la z por ejemplo (definir el alfabeto cuando se trabaja con la 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(az), 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 ingresas tu 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, convierte 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 personaje). Entonces, con un poco de reescritura ()|h(ed?)?|([^h]|h([^e]|e([^d]|d([^e]|e.)))).* .

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

Puntos de referencia

Decidí evaluar algunas de las Opciones presentadas y comparar su rendimiento, así como utilizar algunas características nuevas. Benchmarking en .NET Regex Engine: http://regexhero.net/tester/

Texto de referencia:

Las primeras 7 líneas no deben coincidir, ya que contienen la expresión buscada, mientras que las 7 líneas inferiores deben 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 carreras – Mayor número = 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 

Como .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))*$ resulta en una pequeña ganancia de rendimiento.

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

Con un lookaid negativo, 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 pondrá a prueba de 1 a 4 caracteres más adelante al unir cualquier personaje individual. Podemos evitar esto y dejar que la parte de anticipación revise todo el texto, asegúrese de que no haya ‘hede’, y luego la parte normal (. *) Puede comer todo el texto de una sola vez.

Aquí está la expresión regular mejorada:

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

Tenga en cuenta que el cuantificador perezoso (*?) En la parte negativa de anticipación es opcional, puede usar (*) cuantificador codicioso en su lugar, dependiendo de sus datos: si ‘hede’ sí lo está y al principio la mitad del texto, el cuantificador perezoso puede se 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 acerca de la búsqueda anticipada, consulte el excelente artículo: Mastering 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, puedes 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', // ie, anything contains 'hede' ), _.endOfLine() ); 

No regex, pero me pareció lógico y útil usar greps en serie con tubería para eliminar el ruido.

p.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 grep serial es (no es un comentario) y (coincide con dir)

con esto, evitas probar un vistazo en cada posición:

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

equivalente a (para .net):

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

Respuesta anterior:

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

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 de “desenrollar el bucle” de Friedl y requiere mucho menos retroceso.

Anteriormente (?:(?!hede).)* Es genial porque puede anclarse.

 ^(?:(?!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 las cláusulas “Y” agregadas:

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

Si quieres hacer coincidir un personaje para negar una palabra similar a la clase de carácter de negación:

Por ejemplo, una cadena:

  

No utilice:

  

Utilizar:

  

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

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

El OP no especificó ni etiquetó la publicación para indicar el contexto (lenguaje de progtwigción, editor, herramienta) en el que se usará Regex.

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

Textpad compatible con algunos Regex, pero no es compatible con mirar hacia adelante o mirar hacia atrás, por lo que toma unos pocos pasos.

Si estoy buscando retener todas las líneas que NO contienen el hede cadena, lo haría así:

1. Busque / reemplace el archivo completo para agregar una “Etiqueta” única al comienzo de cada línea que contenga cualquier texto.

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

2. Elimine todas las líneas que contengan hede cadena (la cadena de reemplazo está vacía):

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

3. En este punto, todas las líneas restantes NO contienen el hede cadena. Elimine la “Etiqueta” única de todas las líneas (la cadena de reemplazo está vacía):

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

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


Si estoy buscando hacer algo diferente a solo las líneas que NO contienen el hede cadena, lo haría así:

1. Busque / reemplace el archivo completo para agregar una “Etiqueta” única al comienzo de cada línea que contenga cualquier texto.

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

2. Para todas las líneas que contienen el hede cadena, elimine la “Etiqueta” única:

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

3. En este punto, todas las líneas que comienzan con la “Etiqueta” única, NO contienen el hede cadena. Ahora puedo hacer mi Something Else solo a esas líneas.

4. Cuando termine, elimino la “Etiqueta” única de todas las líneas (la cadena de reemplazo está vacía):

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

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

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

Esto hede completamente la línea que contiene el hede cadena hede y coincide con todas las líneas restantes.

MANIFESTACIÓN

Ejecución de las partes:

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

  1. Parte antes de | símbolo. Parte no debe coincidir .

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

     ^.*$ 

PARTE 1

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

 ^hede$(*SKIP)(*F) 

Explicación:

  • ^ Afirma que estamos en el comienzo.
  • hede Coincide con el hede cadena
  • $ Afirma que estamos al final de la línea.

Entonces la línea que contiene el hede cadena se emparejaría. Una vez que el motor de expresiones regulares ve lo siguiente (*SKIP)(*F) ( Nota: Puede escribir (*F) como (*FAIL) ) verbo, se salta y hace que la coincidencia falle. | llamada alteración u operador OR lógico agregado al lado del verbo PCRE que inturn 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 el hede cadena hede . Vea la demostración aquí . Es decir, intenta hacer coincidir los caracteres de la cadena restante. Ahora la expresión regular en la segunda parte se ejecutará.

PARTE 2

 ^.*$ 

Explicación:

  • ^ Afirma que estamos en el comienzo. es decir, coincide con todos los inicios de línea excepto el de la línea hede . Vea la demostración aquí .
  • .* En el modo Multiline,. coincidiría con cualquier carácter excepto los caracteres 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. Vea la demostración aquí .

    ¿Por qué has añadido. * En lugar de. +?

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

  • $ El ancla de final de línea no es necesaria aquí.

Desde la introducción de ruby-2.4.1, podemos usar el nuevo operador ausente en las expresiones regulares de Ruby

del documento oficial

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

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

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

Dado que nadie más ha dado una respuesta directa a la pregunta que se hizo , 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 solo es necesario para trabajar con Basic Regular Expressions , que simplemente no son lo suficientemente potentes para llevar a cabo esa tarea (no son capaces de analizar los idiomas regulares, debido a la falta de alternancia y agrupamiento).

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 de corchetes negativos, agrupación y la estrella Kleene, y puede anclar al principio y al final de la cadena, eso es todo lo que necesita para este enfoque.

Con GNU grep , sería algo así como:

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

(encontrado con Grail y algunas otras optimizaciones hechas a mano).

También puede usar una herramienta que implemente expresiones regulares extendidas , como egrep , para deshacerse de las barras diagonales inversas:

 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 < 

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 invierta el autómata cambiando cada estado de aceptación por no aceptación y viceversa, y luego convirtiendo el FA resultante de nuevo en una expresión regular.

Finalmente, como todos han notado, si su motor de expresiones regulares admite búsquedas negativas, eso simplifica mucho la tarea. Por ejemplo, con GNU grep:

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

Actualización: Recientemente encontré la excelente biblioteca FormalTheory de Kendall Hopkins, escrita en PHP, que proporciona una funcionalidad similar a Grail. Utilicándolo, y un simplificador escrito por mí mismo, he podido escribir un generador en línea de expresiones regulares negativas con una frase de entrada (solo caracteres alfanuméricos y espaciales admitidos actualmente): 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.

It may be more maintainable to two regexes in your code, one to do the first match, and then if it matches run the second regex to check for outlier cases you wish to block for example ^.*(hede).* then have appropriate logic in your code.

OK, I admit this is not really an answer to the posted question posted and it may also use slightly more processing than a single regex. But for developers who came here looking for a fast emergency fix for an outlier case then this solution should not be overlooked.

The TXR Language supports regex negation.

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

A more complicated example: match all lines that start with a and end with z , but do not contain the substring 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 

Regex negation is not particularly useful on its own but when you also have intersection, things get interesting, since you have a full set of boolean set operations: you can express "the set which matches this, except for things which match that".

The below function will help you get your desired output

  0 ) { foreach($propositions as $exceptionPhrase) { $text = preg_replace($exceptionPhrase, '', trim($text)); } $retval = trim($text); } return $retval; } ?> 

A simpler solution is to use the not operator !

Your if statement will need to match “contains” and not match “excludes”.

 var contains = /abc/; var excludes =/hede/; if(string.match(contains) && !(string.match(excludes))){ //proceed... 

I believe the designers of RegEx anticipated the use of not operators.

How to use PCRE’s backtracking control verbs to match a line not containing a word

Here’s a method that I haven’t seen used before:

 /.*hede(*COMMIT)^|/ 

Cómo funciona

First, it tries to find “hede” somewhere in the line. If successful, at this point, (*COMMIT) tells the engine to, not only not backtrack in the event of a failure, but also not to attempt any further matching in that case. Then, we try to match something that cannot possibly match (in this case, ^ ).

If a line does not contain “hede” then the second alternative, an empty subpattern, successfully matches the subject string.

This method is no more efficient than a negative lookahead, but I figured I’d just throw it on here in case someone finds it nifty and finds a use for it for other, more interesting applications.

Maybe you’ll find this on Google while trying to write a regex that is able to match segments of a line (as opposed to entire lines) which do not contain a substring. Tooke me a while to figure out, so I’ll share:

Given a string: barfoobaz

I want to match tags which do not contain the substring “bad”.

/ will match and .

Notice that there are two sets (layers) of parentheses:

  • The innermost one is for the negative lookahead (it is not a capture group)
  • The outermost was interpreted by Ruby as capture group but we don’t want it to be a capture group, so I added ?: at it’s beginning and it is no longer interpreted as a capture group.

Demo in Ruby:

 s = 'barfoobaz' s.scan(//) # => ["", ""] 

I don’t understand the need for complex regex or even lookaheads here :

 /hede|^(.*)$/gm 

Don’t put in a capturing group the thing you don’t want, but use one for everything else. This will match all lines that don’t contain “hede”.

With ConyEdit , you can use the command line cc.gl !/hede/ to get lines that do not contain the regex matching, or use the command line cc.dl /hede/ to delete lines that contain the regex matching. They have the same result.

Intereting Posts