regex - online - ¿Cómo negar palabras específicas en expresiones regulares?
javascript regex example (10)
A menos que el rendimiento sea lo más importante, a menudo es más fácil ejecutar los resultados a través de una segunda pasada, omitiendo aquellos que coincidan con las palabras que quiere negar.
Las expresiones regulares generalmente significan que estás haciendo scripts o algún tipo de tarea de bajo rendimiento de todos modos, así que encuentra una solución que sea fácil de leer, entender y mantener.
Sé que puedo negar el grupo de caracteres como en [^bar]
pero necesito una expresión regular donde la negación se aplique a la palabra específica, así que en mi ejemplo, ¿cómo puedo negar una "bar"
real y no "any chars in bar"
?
Espero complementar la respuesta.
Como el tutorial específico de expresión regular de Chris es un mejor recurso para aprender expresiones regulares.
Sin embargo, realmente tomó tiempo para leer.
Hago una hoja de trucos para la conveniencia mnemotécnica.
[]
, ()
, {}
liderando cada clase que es fácil de recordar.
Regex =
{''single_character'': [''[]'', ''.'', {''negate'':''^''}],
''capturing_group'' : [''()'', ''|'', ''//', ''backreferences and named group''],
''repetition'' : [''{}'', ''*'', ''+'', ''?'', ''greedy v.s. lazy''],
''anchor'' : [''^'', ''/b'', ''$''],
''non_printable'' : [''/n'', ''/t'', ''/r'', ''/f'', ''/v''],
''shorthand'' : [''/d'', ''/w'', ''/s''],
}
La respuesta aceptada es buena, pero es realmente una solución alternativa para la falta de un operador de negación de subexpresión simple en expresiones regulares. Es por esto que grep --invert-match
sale. Entonces, en * nixes, puede lograr el resultado deseado utilizando tuberías y una segunda expresión regular.
grep ''something I want'' | grep --invert-match ''but not these ones''
Todavía una solución, pero tal vez más fácil de recordar.
La siguiente expresión regular hará lo que usted desea (siempre que se admitan los aspectos negativos de look y downaheads), haciendo coincidir las cosas correctamente; el único problema es que coincide con caracteres individuales (es decir, cada coincidencia es un solo carácter en lugar de todos los caracteres entre dos "barras" consecutivas), lo que posiblemente genere una gran sobrecarga si trabaja con cadenas muy largas.
b(?!ar)|(?<!b)a|a(?!r)|(?<!ba)r|[^bar]
Me encontré con este hilo del foro al intentar identificar una expresión regular para la siguiente declaración en inglés:
Dada una cadena de entrada, haga coincidir todo a menos que esta cadena de entrada sea exactamente ''barra''; por ejemplo, quiero hacer coincidir ''barrera'' y ''desbarbar'' así como ''foo''.
Aquí está la expresión regular que se me ocurrió
^(bar.+|(?!bar).*)$
Mi traducción al inglés de la expresión regular es "coincide con la cadena si comienza con ''barra'' y tiene al menos otro carácter, o si la cadena no comienza con ''barra''.
Puede usar un look-ahead negativo o look-behind :
^(?!.*?bar).*
^(.(?<!bar))*?$
O use solo lo básico:
^(?:[^b]+|b(?:$|[^a]|a(?:$|[^r])))*$
Todos estos coinciden con cualquier cosa que no contenga bar
.
Solo pensé en otra cosa que se podría hacer. Es muy diferente de mi primera respuesta, ya que no usa expresiones regulares, así que decidí hacer una segunda respuesta.
Use el método split()
su idioma de elección en la cadena con la palabra para negar como el argumento sobre qué dividir. Un ejemplo usando Python:
>>> text = ''barbarasdbarbar 1234egb ar bar32 sdfbaraadf''
>>> text.split(''bar'')
['''', '''', ''asd'', '''', '' 1234egb ar '', ''32 sdf'', ''aadf'']
Lo bueno de hacerlo de esta manera, al menos en Python (no recuerdo si la funcionalidad sería la misma en, digamos, Visual Basic o Java), es que le permite saber indirectamente cuándo se repitió "barra" en la cadena debido al hecho de que las cadenas vacías entre "barras" se incluyen en la lista de resultados (aunque la cadena vacía al principio se debe a que hay una "barra" al comienzo de la cadena). Si no desea eso, simplemente puede eliminar las cadenas vacías de la lista.
Tenía una lista de nombres de archivos, y quería excluir algunos, con este tipo de comportamiento (Ruby):
files = [
''mydir/states.rb'', # don''t match these
''countries.rb'',
''mydir/states_bkp.rb'', # match these
''mydir/city_states.rb''
]
excluded = [''states'', ''countries'']
# set my_rgx here
result = WankyAPI.filter(files, my_rgx) # I didn''t write WankyAPI...
assert result == [''mydir/city_states.rb'', ''mydir/states_bkp.rb'']
Aquí está mi solución:
excluded_rgx = excluded.map{|e| e+''/.''}.join(''|'')
my_rgx = /(^|//)((?!#{excluded_rgx})[^/.//]*)/.rb$/
Mis suposiciones para esta aplicación:
- La cadena que debe excluirse está al principio de la entrada, o inmediatamente después de una barra diagonal.
- Las cadenas permitidas terminan con
.rb
. - Los nombres de archivo permitidos no tienen un
.
personaje antes de la.rb
.
Una excelente manera de hacer esto es usar lookahead negativo :
^(?!.*bar).*$
Solución:
^(?!.*STRING1|.*STRING2|.*STRING3).*$
xxxxxx ok
xxxSTRING1xxx KO (es si se desea)
xxxSTRING2xxx KO (es si se desea)
xxxSTRING3xxx KO (es si se desea)