Cómo filtrar caracteres no alfanuméricos de cadenas (strings) de Python

PythonPythonBeginner
Practicar Ahora

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En la programación en Python, trabajar con cadenas de texto es una habilidad fundamental. A menudo, es necesario limpiar datos de texto eliminando caracteres especiales, signos de puntuación u otros caracteres no alfanuméricos. Este proceso es esencial para diversas aplicaciones, como el análisis de datos, el procesamiento del lenguaje natural y el desarrollo web.

Este tutorial lo guía a través de diferentes métodos para filtrar caracteres no alfanuméricos de cadenas de texto en Python. Al final, podrá transformar texto desordenado en datos limpios y estructurados que sean más fáciles de procesar en sus aplicaciones de Python.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/BasicConceptsGroup(["Basic Concepts"]) python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/FileHandlingGroup(["File Handling"]) python(("Python")) -.-> python/AdvancedTopicsGroup(["Advanced Topics"]) python/BasicConceptsGroup -.-> python/strings("Strings") python/FunctionsGroup -.-> python/build_in_functions("Build-in Functions") python/FileHandlingGroup -.-> python/file_reading_writing("Reading and Writing Files") python/AdvancedTopicsGroup -.-> python/regular_expressions("Regular Expressions") subgraph Lab Skills python/strings -.-> lab-415420{{"Cómo filtrar caracteres no alfanuméricos de cadenas (strings) de Python"}} python/build_in_functions -.-> lab-415420{{"Cómo filtrar caracteres no alfanuméricos de cadenas (strings) de Python"}} python/file_reading_writing -.-> lab-415420{{"Cómo filtrar caracteres no alfanuméricos de cadenas (strings) de Python"}} python/regular_expressions -.-> lab-415420{{"Cómo filtrar caracteres no alfanuméricos de cadenas (strings) de Python"}} end

Conceptos básicos de cadenas de texto en Python y caracteres alfanuméricos

Antes de adentrarnos en el filtrado de caracteres no alfanuméricos, entendamos qué son las cadenas de texto y los caracteres alfanuméricos en Python.

¿Qué son las cadenas de texto en Python?

Las cadenas de texto en Python son secuencias de caracteres encerradas entre comillas. Puedes usar comillas simples ('), dobles (") o triples (''' o """) para definir cadenas de texto.

Vamos a crear un nuevo archivo de Python para experimentar con cadenas de texto. En el WebIDE, crea un nuevo archivo en el directorio /home/labex/project haciendo clic en el icono "Nuevo archivo" en el panel del explorador. Nombrar el archivo string_basics.py.

Agrega el siguiente código al archivo:

## Different ways to define strings in Python
string1 = 'Hello, World!'
string2 = "Python Programming"
string3 = '''This is a
multiline string.'''

## Display each string
print("String 1:", string1)
print("String 2:", string2)
print("String 3:", string3)

Para ejecutar este archivo, abre una terminal (si no está abierta) y ejecuta:

python3 /home/labex/project/string_basics.py

Deberías ver una salida similar a:

String 1: Hello, World!
String 2: Python Programming
String 3: This is a
multiline string.

¿Qué son los caracteres alfanuméricos?

Los caracteres alfanuméricos incluyen:

  • Letras (A-Z, a-z)
  • Números (0-9)

Cualquier otro carácter (como signos de puntuación, espacios, símbolos) se considera no alfanumérico.

Vamos a crear otro archivo para verificar si un carácter es alfanumérico. Crea un nuevo archivo llamado alphanumeric_check.py con el siguiente contenido:

## Check if characters are alphanumeric
test_string = "Hello123!@#"

print("Testing each character in:", test_string)
print("Character | Alphanumeric?")
print("-" * 24)

for char in test_string:
    is_alnum = char.isalnum()
    print(f"{char:^9} | {is_alnum}")

## Check entire strings
examples = ["ABC123", "Hello!", "12345", "a b c"]
print("\nChecking entire strings:")
for ex in examples:
    print(f"{ex:10} | {ex.isalnum()}")

Ejecuta este archivo:

python3 /home/labex/project/alphanumeric_check.py

Deberías ver una salida que muestra qué caracteres son alfanuméricos y cuáles no:

Testing each character in: Hello123!@#
Character | Alphanumeric?
------------------------
    H     | True
    e     | True
    l     | True
    l     | True
    o     | True
    1     | True
    2     | True
    3     | True
    !     | False
    @     | False
    ##     | False

Checking entire strings:
ABC123     | True
Hello!     | False
12345      | True
a b c      | False

Como puedes ver, el método isalnum() devuelve True para letras y números y False para cualquier otro carácter. Esto será útil cuando necesitemos identificar caracteres no alfanuméricos.

Filtrado con métodos de cadenas de texto

Python proporciona varios métodos integrados para cadenas de texto que pueden ayudarnos a filtrar caracteres no alfanuméricos. En este paso, exploraremos estos métodos y crearemos nuestra propia función de filtrado.

Uso de comprensión de cadenas

Un enfoque común para filtrar caracteres es utilizar la comprensión de cadenas. Vamos a crear un nuevo archivo llamado string_filter.py:

## Using string comprehension to filter non-alphanumeric characters

def filter_alphanumeric(text):
    ## Keep only alphanumeric characters
    filtered_text = ''.join(char for char in text if char.isalnum())
    return filtered_text

## Test the function with different examples
test_strings = [
    "Hello, World!",
    "Python 3.10 is amazing!",
    "Email: [email protected]",
    "Phone: (123) 456-7890"
]

print("Original vs Filtered:")
print("-" * 40)

for text in test_strings:
    filtered = filter_alphanumeric(text)
    print(f"Original: {text}")
    print(f"Filtered: {filtered}")
    print("-" * 40)

Ejecuta este archivo:

python3 /home/labex/project/string_filter.py

Deberías ver una salida como esta:

Original vs Filtered:
----------------------------------------
Original: Hello, World!
Filtered: HelloWorld
----------------------------------------
Original: Python 3.10 is amazing!
Filtered: Python310isamazing
----------------------------------------
Original: Email: [email protected]
Filtered: Emailuserexamplecom
----------------------------------------
Original: Phone: (123) 456-7890
Filtered: Phone1234567890
----------------------------------------

La función filter_alphanumeric() itera a través de cada carácter en la cadena de texto y solo conserva aquellos que pasan la comprobación isalnum().

Uso de la función filter()

La función integrada filter() de Python proporciona otra forma de lograr el mismo resultado. Vamos a agregar este método a nuestro archivo:

## Add to the string_filter.py file

def filter_alphanumeric_using_filter(text):
    ## Using the built-in filter() function
    filtered_text = ''.join(filter(str.isalnum, text))
    return filtered_text

print("\nUsing the filter() function:")
print("-" * 40)

for text in test_strings:
    filtered = filter_alphanumeric_using_filter(text)
    print(f"Original: {text}")
    print(f"Filtered: {filtered}")
    print("-" * 40)

Abre el archivo string_filter.py en el WebIDE y agrega el código anterior al final del archivo. Luego, ejecútalo nuevamente:

python3 /home/labex/project/string_filter.py

Verás que ambos métodos producen los mismos resultados.

Filtrado personalizado

A veces, es posible que desees conservar algunos caracteres no alfanuméricos mientras eliminas otros. Vamos a agregar una función que nos permita especificar qué caracteres adicionales se deben conservar:

## Add to the string_filter.py file

def custom_filter(text, keep_chars=""):
    ## Keep alphanumeric characters and any characters specified in keep_chars
    filtered_text = ''.join(char for char in text if char.isalnum() or char in keep_chars)
    return filtered_text

print("\nCustom filtering (keeping spaces and @):")
print("-" * 40)

for text in test_strings:
    filtered = custom_filter(text, keep_chars=" @")
    print(f"Original: {text}")
    print(f"Filtered: {filtered}")
    print("-" * 40)

Agrega este código al final de tu archivo string_filter.py y ejecútalo nuevamente:

python3 /home/labex/project/string_filter.py

Ahora verás que los espacios y los símbolos @ se conservan en los resultados filtrados, lo cual puede ser útil cuando necesitas mantener cierto formato o caracteres especiales.

Uso de expresiones regulares para la limpieza de texto

Las expresiones regulares (regex) proporcionan una forma poderosa de identificar y manipular patrones en el texto. El módulo re de Python ofrece funciones para trabajar con expresiones regulares.

Introducción a las expresiones regulares básicas para el filtrado de caracteres

Vamos a crear un nuevo archivo llamado regex_filter.py:

## Using regular expressions to filter non-alphanumeric characters
import re

def filter_with_regex(text):
    ## Replace all non-alphanumeric characters with an empty string
    filtered_text = re.sub(r'[^a-zA-Z0-9]', '', text)
    return filtered_text

## Test the function with different examples
test_strings = [
    "Hello, World!",
    "Python 3.10 is amazing!",
    "Email: [email protected]",
    "Phone: (123) 456-7890"
]

print("Original vs Regex Filtered:")
print("-" * 40)

for text in test_strings:
    filtered = filter_with_regex(text)
    print(f"Original: {text}")
    print(f"Filtered: {filtered}")
    print("-" * 40)

El patrón de expresión regular [^a-zA-Z0-9] coincide con cualquier carácter que NO sea una letra mayúscula, una letra minúscula o un dígito. La función re.sub() reemplaza todos los caracteres coincidentes con una cadena vacía.

Ejecuta el archivo:

python3 /home/labex/project/regex_filter.py

Deberías ver una salida similar a:

Original vs Regex Filtered:
----------------------------------------
Original: Hello, World!
Filtered: HelloWorld
----------------------------------------
Original: Python 3.10 is amazing!
Filtered: Python310isamazing
----------------------------------------
Original: Email: [email protected]
Filtered: Emailuserexamplecom
----------------------------------------
Original: Phone: (123) 456-7890
Filtered: Phone1234567890
----------------------------------------

Patrones personalizados con expresiones regulares

Las expresiones regulares permiten patrones y reemplazos más complejos. Vamos a agregar una función que permita patrones personalizados:

## Add to the regex_filter.py file

def custom_regex_filter(text, pattern=r'[^a-zA-Z0-9]', replacement=''):
    ## Replace characters matching the pattern with the replacement
    filtered_text = re.sub(pattern, replacement, text)
    return filtered_text

print("\nCustom regex filtering (keeping spaces and some punctuation):")
print("-" * 60)

## Keep alphanumeric chars, spaces, and @.
custom_pattern = r'[^a-zA-Z0-9\s@\.]'

for text in test_strings:
    filtered = custom_regex_filter(text, pattern=custom_pattern)
    print(f"Original: {text}")
    print(f"Filtered: {filtered}")
    print("-" * 60)

El patrón [^a-zA-Z0-9\s@\.] coincide con cualquier carácter que NO sea un carácter alfanumérico, un espacio en blanco (\s), el símbolo @ o un punto. Agrega este código a tu archivo regex_filter.py y ejecútalo nuevamente:

python3 /home/labex/project/regex_filter.py

Identificación de caracteres no alfanuméricos

A veces, es posible que desees identificar qué caracteres no alfanuméricos están presentes en una cadena. Vamos a agregar una función para identificar estos caracteres:

## Add to the regex_filter.py file

def identify_non_alphanumeric(text):
    ## Find all non-alphanumeric characters in the text
    non_alphanumeric = re.findall(r'[^a-zA-Z0-9]', text)
    ## Return unique characters as a set
    return set(non_alphanumeric)

print("\nIdentifying non-alphanumeric characters:")
print("-" * 40)

for text in test_strings:
    characters = identify_non_alphanumeric(text)
    print(f"Text: {text}")
    print(f"Non-alphanumeric characters: {characters}")
    print("-" * 40)

Agrega este código a tu archivo regex_filter.py y ejecútalo nuevamente:

python3 /home/labex/project/regex_filter.py

La salida te mostrará qué caracteres no alfanuméricos están presentes en cada cadena, lo cual puede ser útil para entender qué se debe filtrar en tus datos.

Aplicaciones reales de limpieza de texto

Ahora que hemos aprendido diferentes métodos para filtrar caracteres no alfanuméricos, apliquemos estas técnicas a escenarios del mundo real.

Limpieza de la entrada del usuario

La entrada del usuario a menudo contiene caracteres inesperados que deben ser limpiados. Creemos un archivo llamado text_cleaning_app.py para demostrar esto:

## Text cleaning application for user input
import re

def clean_username(username):
    """Cleans a username by removing special characters and spaces"""
    return re.sub(r'[^a-zA-Z0-9_]', '', username)

def clean_search_query(query):
    """Preserves alphanumeric chars and spaces, replaces multiple spaces with one"""
    ## First, replace non-alphanumeric chars (except spaces) with empty string
    cleaned = re.sub(r'[^a-zA-Z0-9\s]', '', query)
    ## Then, replace multiple spaces with a single space
    cleaned = re.sub(r'\s+', ' ', cleaned)
    ## Finally, strip leading and trailing spaces
    return cleaned.strip()

## Simulate user input
usernames = [
    "john.doe",
    "user@example",
    "my username!",
    "admin_123"
]

search_queries = [
    "python   programming",
    "how to filter?!  special chars",
    "$ regex      examples $",
    "   string methods   "
]

## Clean and display usernames
print("Username Cleaning:")
print("-" * 40)
for username in usernames:
    cleaned = clean_username(username)
    print(f"Original: {username}")
    print(f"Cleaned:  {cleaned}")
    print("-" * 40)

## Clean and display search queries
print("\nSearch Query Cleaning:")
print("-" * 40)
for query in search_queries:
    cleaned = clean_search_query(query)
    print(f"Original: '{query}'")
    print(f"Cleaned:  '{cleaned}'")
    print("-" * 40)

Ejecuta este archivo:

python3 /home/labex/project/text_cleaning_app.py

Manejo de datos de archivos

Creemos un archivo de texto de muestra y limpiemos su contenido. Primero, crea un archivo llamado sample_data.txt con el siguiente contenido:

User1: [email protected] (Active: Yes)
User2: [email protected] (Active: No)
User3: admin#[email protected] (Active: Yes)
Notes: Users should change their passwords every 90 days!

Puedes crear este archivo utilizando el editor del WebIDE. Ahora, creemos un archivo llamado file_cleaner.py para limpiar estos datos:

## File cleaning application
import re

def extract_emails(text):
    """Extract email addresses from text"""
    ## Simple regex for email extraction
    email_pattern = r'[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+'
    return re.findall(email_pattern, text)

def extract_usernames(text):
    """Extract the username part from email addresses"""
    emails = extract_emails(text)
    usernames = [email.split('@')[0] for email in emails]
    return usernames

def clean_usernames(usernames):
    """Clean usernames by removing non-alphanumeric characters"""
    return [re.sub(r'[^a-zA-Z0-9]', '', username) for username in usernames]

## Read the sample data file
try:
    with open('/home/labex/project/sample_data.txt', 'r') as file:
        data = file.read()
except FileNotFoundError:
    print("Error: sample_data.txt file not found!")
    exit(1)

## Process the data
print("File Cleaning Results:")
print("-" * 50)
print("Original data:")
print(data)
print("-" * 50)

## Extract emails
emails = extract_emails(data)
print(f"Extracted {len(emails)} email addresses:")
for email in emails:
    print(f"  - {email}")

## Extract and clean usernames
usernames = extract_usernames(data)
cleaned_usernames = clean_usernames(usernames)

print("\nUsername extraction and cleaning:")
for i, (original, cleaned) in enumerate(zip(usernames, cleaned_usernames)):
    print(f"  - User {i+1}: {original} → {cleaned}")

print("-" * 50)

Ejecuta este archivo:

python3 /home/labex/project/file_cleaner.py

Comparación de rendimiento

Diferentes métodos de filtrado pueden tener diferentes características de rendimiento. Creemos un archivo llamado performance_test.py para compararlos:

## Performance comparison of different filtering methods
import re
import time

def filter_with_loop(text):
    """Filter using a simple loop"""
    result = ""
    for char in text:
        if char.isalnum():
            result += char
    return result

def filter_with_comprehension(text):
    """Filter using list comprehension"""
    return ''.join(char for char in text if char.isalnum())

def filter_with_filter_function(text):
    """Filter using the built-in filter function"""
    return ''.join(filter(str.isalnum, text))

def filter_with_regex(text):
    """Filter using regular expressions"""
    return re.sub(r'[^a-zA-Z0-9]', '', text)

def filter_with_translate(text):
    """Filter using string.translate"""
    ## Create a translation table that maps all non-alphanumeric chars to None
    from string import ascii_letters, digits
    allowed = ascii_letters + digits
    translation_table = str.maketrans('', '', ''.join(c for c in map(chr, range(128)) if c not in allowed))
    return text.translate(translation_table)

## Generate test data (a string with a mix of alphanumeric and other characters)
test_data = "".join(chr(i) for i in range(33, 127)) * 1000  ## ASCII printable characters repeated

## Define the filtering methods to test
methods = [
    ("Simple Loop", filter_with_loop),
    ("List Comprehension", filter_with_comprehension),
    ("Filter Function", filter_with_filter_function),
    ("Regular Expression", filter_with_regex),
    ("String Translate", filter_with_translate)
]

print("Performance Comparison:")
print("-" * 60)
print(f"Test data length: {len(test_data)} characters")
print("-" * 60)
print(f"{'Method':<20} | {'Time (seconds)':<15} | {'Characters Removed':<20}")
print("-" * 60)

## Test each method
for name, func in methods:
    start_time = time.time()
    result = func(test_data)
    end_time = time.time()

    execution_time = end_time - start_time
    chars_removed = len(test_data) - len(result)

    print(f"{name:<20} | {execution_time:<15.6f} | {chars_removed:<20}")

print("-" * 60)

Ejecuta este archivo:

python3 /home/labex/project/performance_test.py

La salida te mostrará qué método es el más eficiente para filtrar caracteres no alfanuméricos, lo cual puede ser importante cuando se procesan grandes cantidades de datos de texto.

Resumen

En este laboratorio (lab), has aprendido varios métodos para filtrar caracteres no alfanuméricos de cadenas (strings) de Python:

  1. Métodos de cadenas: Utilizando los métodos integrados de cadenas de Python como isalnum() para verificar y filtrar caracteres.
  2. Comprensión y filtrado: Empleando comprensión de listas y la función integrada filter() para crear cadenas limpias.
  3. Expresiones regulares: Aprovechando el módulo re de Python para realizar coincidencias de patrones y reemplazos potentes.
  4. Aplicaciones del mundo real: Aplicando estas técnicas a escenarios prácticos, como la limpieza de la entrada del usuario, el procesamiento de datos de archivos y la comparación de rendimiento.

Estas técnicas son fundamentales para tareas de procesamiento de texto en diversos dominios, incluyendo:

  • Limpieza de datos en análisis de datos y aprendizaje automático (machine learning)
  • Procesamiento de lenguaje natural
  • Extracción de datos y web scraping
  • Validación de la entrada del usuario en aplicaciones web

Al dominar estos métodos, ahora tienes las habilidades necesarias para transformar datos de texto desordenados en formatos limpios y estructurados, que son más fáciles de analizar y procesar en tus aplicaciones de Python.