sub online ignorecase escape ejemplos python regex string

python - online - ¿Cómo verifico que una cadena solo contiene letras, números, guiones bajos y guiones?



python split regex (10)

Sé cómo hacer esto si repito todos los caracteres de la cadena, pero estoy buscando un método más elegante.


¡use una expresión regular y vea si coincide!

([a-z][A-Z][0-9]/_/-)*


Aquí hay algo basado en el "enfoque ingenuo" de Jerub (¡siendo ingenuo sus palabras, no las mías!):

import string ALLOWED = frozenset(string.ascii_letters + string.digits + ''_'' + ''-'') def check(mystring): return all(c in ALLOWED for c in mystring)

Si ALLOWED era una cadena, entonces creo que c in ALLOWED implicaría iterar sobre cada carácter en la cadena hasta que encuentre una coincidencia o llegue al final. Lo cual, para citar a Joel Spolsky, es algo así como un algoritmo de Shlemiel the Painter .

Pero probar la existencia en un conjunto debería ser más eficiente, o al menos menos dependiente de la cantidad de caracteres permitidos. Ciertamente, este enfoque es un poco más rápido en mi máquina. Está claro y creo que funciona bastante bien para la mayoría de los casos (en mi máquina lenta puedo validar decenas de miles de cadenas cortas en una fracción de segundo). Me gusta.

REALMENTE en mi máquina una expresión regular funciona varias veces más rápido, y es tan simple como esto (podría decirse que más simple). Entonces, ese es probablemente el mejor camino a seguir.


Bueno, puedes pedir la ayuda de Regex, el gran aquí :)

código:

import re string = ''adsfg34wrtwe4r2_()'' #your string that needs to be matched. regex = r''^[/w/d_()]*$'' # you can also add a space in regex if u want to allow it in the string if re.match(regex,string): print ''yes'' else: print ''false''

Salida:

yes

Espero que esto ayude :)


Como alternativa al uso de expresiones regulares, puedes hacerlo en Conjuntos:

from sets import Set allowed_chars = Set(''0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-'') if Set(my_little_sting).issubset(allowed_chars): # your action print True


Hay una variedad de formas de lograr este objetivo, algunas son más claras que otras. Para cada uno de mis ejemplos, ''Verdadero'' significa que la secuencia que se pasa es válida, ''Falsa'' significa que contiene caracteres no válidos.

En primer lugar, está el enfoque ingenuo:

import string allowed = string.letters + string.digits + ''_'' + ''-'' def check_naive(mystring): return all(c in allowed for c in mystring)

Luego está el uso de una expresión regular, puede hacer esto con re.match (). Tenga en cuenta que ''-'' debe estar al final de [] de lo contrario se usará como un delimitador ''rango''. También tenga en cuenta el $ que significa ''final de la cadena''. Otras respuestas indicadas en esta pregunta usan una clase de caracteres especial, ''/ w'', siempre prefiero usar un rango de clase de caracteres explícito usando [] porque es más fácil de entender sin tener que buscar una guía de referencia rápida, y más fácil de especializar. caso.

import re CHECK_RE = re.compile(''[a-zA-Z0-9_-]+$'') def check_re(mystring): return CHECK_RE.match(mystring)

Otra solución señaló que puede hacer una combinación inversa con expresiones regulares, lo he incluido aquí ahora. Tenga en cuenta que [^ ...] invierte la clase de caracteres porque se usa ^

CHECK_INV_RE = re.compile(''[^a-zA-Z0-9_-]'') def check_inv_re(mystring): return not CHECK_INV_RE.search(mystring)

También puede hacer algo complicado con el objeto ''establecer''. Eche un vistazo a este ejemplo, que elimina de la cadena original todos los caracteres que están permitidos, dejándonos con un conjunto que contiene a) nada, o b) los caracteres ofensivos de la cadena:

def check_set(mystring): return not set(mystring) - set(allowed)


Si no fuera por los guiones y los guiones bajos, la solución más fácil sería

my_little_string.isalnum()

(Sección 3.6.1 de la Referencia de la Biblioteca de Python)


Siempre puedes usar una lista de comprensión y verificar los resultados con todo, sería un poco menos intensivo en recursos que usar una expresión regular: all([c in string.letters + string.digits + ["_", "-"] for c in mystring])


Una expresión regular hará el truco con muy poco código:

import re ... if re.match("^[A-Za-z0-9_-]*$", my_little_string): # do something here


[Editar] Hay otra solución aún no mencionada, y parece superar a los otros dados hasta ahora en la mayoría de los casos.

Utilice string.translate para reemplazar todos los caracteres válidos en la cadena, y vea si nos quedan algunos inválidos. Esto es bastante rápido ya que usa la función C subyacente para hacer el trabajo, con muy poco bytecode de python involucrado.

Obviamente, el rendimiento no lo es todo; ir por las soluciones más legibles es probablemente el mejor enfoque cuando no está en un código de ruta crítico, pero para ver cómo se compaginan las soluciones, aquí hay una comparación de rendimiento de todos los métodos propuestos hasta ahora. check_trans es el que usa el método string.translate.

Código de prueba:

import string, re, timeit pat = re.compile(''[/w-]*$'') pat_inv = re.compile (''[^/w-]'') allowed_chars=string.ascii_letters + string.digits + ''_-'' allowed_set = set(allowed_chars) trans_table = string.maketrans('''','''') def check_set_diff(s): return not set(s) - allowed_set def check_set_all(s): return all(x in allowed_set for x in s) def check_set_subset(s): return set(s).issubset(allowed_set) def check_re_match(s): return pat.match(s) def check_re_inverse(s): # Search for non-matching character. return not pat_inv.search(s) def check_trans(s): return not s.translate(trans_table,allowed_chars) test_long_almost_valid=''a_very_long_string_that_is_mostly_valid_except_for_last_char''*99 + ''!'' test_long_valid=''a_very_long_string_that_is_completely_valid_'' * 99 test_short_valid=''short_valid_string'' test_short_invalid=''/$%$%&'' test_long_invalid=''/$%$%&'' * 99 test_empty='''' def main(): funcs = sorted(f for f in globals() if f.startswith(''check_'')) tests = sorted(f for f in globals() if f.startswith(''test_'')) for test in tests: print "Test %-15s (length = %d):" % (test, len(globals()[test])) for func in funcs: print " %-20s : %.3f" % (func, timeit.Timer(''%s(%s)'' % (func, test), ''from __main__ import pat,allowed_set,%s'' % '',''.join(funcs+tests)).timeit(10000)) print if __name__==''__main__'': main()

Los resultados en mi sistema son:

Test test_empty (length = 0): check_re_inverse : 0.042 check_re_match : 0.030 check_set_all : 0.027 check_set_diff : 0.029 check_set_subset : 0.029 check_trans : 0.014 Test test_long_almost_valid (length = 5941): check_re_inverse : 2.690 check_re_match : 3.037 check_set_all : 18.860 check_set_diff : 2.905 check_set_subset : 2.903 check_trans : 0.182 Test test_long_invalid (length = 594): check_re_inverse : 0.017 check_re_match : 0.015 check_set_all : 0.044 check_set_diff : 0.311 check_set_subset : 0.308 check_trans : 0.034 Test test_long_valid (length = 4356): check_re_inverse : 1.890 check_re_match : 1.010 check_set_all : 14.411 check_set_diff : 2.101 check_set_subset : 2.333 check_trans : 0.140 Test test_short_invalid (length = 6): check_re_inverse : 0.017 check_re_match : 0.019 check_set_all : 0.044 check_set_diff : 0.032 check_set_subset : 0.037 check_trans : 0.015 Test test_short_valid (length = 18): check_re_inverse : 0.125 check_re_match : 0.066 check_set_all : 0.104 check_set_diff : 0.051 check_set_subset : 0.046 check_trans : 0.017

El enfoque de traducción parece ser el mejor en la mayoría de los casos, de forma espectacular con cadenas largas válidas, pero es superado por expresiones regulares en test_long_invalid (Presumiblemente porque la expresión regular puede rescatar inmediatamente, pero la traducción siempre tiene que analizar toda la cadena). Los enfoques establecidos suelen ser peores, superando las expresiones regulares solo para el caso de cadena vacía.

Usar todo (x en permitido_juego para x en s) funciona bien si se rescata temprano, pero puede ser malo si tiene que recorrer cada carácter. isSubSet y set difference son comparables, y son consistentemente proporcionales a la longitud de la cadena, independientemente de los datos.

Hay una diferencia similar entre los métodos regex que coinciden con todos los caracteres válidos y la búsqueda de caracteres no válidos. La coincidencia funciona un poco mejor cuando se busca una cadena larga, pero totalmente válida, pero peor para los caracteres no válidos cerca del final de la cadena.


pat = re.compile (''[^/w-]'') def onlyallowed(s): return not pat.search (s)