Búsqueda y filtrado de texto

Búsqueda y filtrado de texto

En Linux, la combinación de grep, sed, awk, find, xargs y utilidades como cut, sort, uniq permite localizar, transformar y resumir información de archivos de texto plano (logs, CSV, FASTA/FASTQ, etc.).
Esta sección presenta una guía práctica, con ejemplos reproducibles y casos bioinformáticos.

Recomendación: Usa un directorio de trabajo separado para no mezclar con tus datos reales.


0) Preparación: datos de ejemplo (reproducible)

Ejecuta este bloque para crear una carpeta demo_text con archivos de prueba:

# Crear carpeta y entrar
mkdir -p demo_text && cd demo_text

# 1) FASTA pequeño
cat > genes.fasta <<'FA'
>geneA|Arabidopsis_thaliana
ATGAAACCCGGGTTTAAACCC
>geneB|Mammillaria_haageana
ATGAATTTNNNCCCGGGTTTA
>geneC|Zea_mays
ATGCCCGGGTTAACCGGTTAA
FA

# 2) FASTQ minimal (2 lecturas)
cat > reads.fastq <<'FQ'
@SEQ_ID_1
ACGTTTCCCGGAA
+
FFF:::FFFFF::
@SEQ_ID_2
NNNNACGTACGTN
+
!!''(((****))
FQ

# 3) CSV simple (expresión)
cat > expr.csv <<'CSV'
gene,sample,counts
geneA,S1,12
geneA,S2,3
geneB,S1,0
geneB,S2,27
geneC,S1,8
geneC,S2,8
CSV

# 4) Log con fechas
cat > app.log <<'LOG'
2025-08-01 10:00:01 INFO start pipeline
2025-08-01 10:00:02 WARN low memory
2025-08-01 10:00:03 ERROR read failed on sample S1
2025-08-01 10:01:01 INFO retry sample S1
2025-08-01 10:02:10 INFO done
LOG

1) grep: encontrar líneas que coinciden con un patrón

Sintaxis básica:

grep [opciones] 'patrón' archivo(s)

1.1 Búsquedas simples

# Buscar "geneA" en FASTA
grep 'geneA' genes.fasta

# Insensible a mayúsculas/minúsculas
grep -i 'zeA' genes.fasta

# Solo nombre de archivo con coincidencias
grep -l 'gene' *.fasta

1.2 Mostrar contexto y número de línea

# Número de línea (-n) y coincidencia resaltada (--color)
grep -n --color 'INFO' app.log

# Contexto: 1 línea antes y 2 después
grep -n -C2 'ERROR' app.log

# Solo antes (-B) o solo después (-A)
grep -n -B1 'WARN' app.log

1.3 Contar coincidencias y ver solo el match

# Contar líneas que contienen 'geneA'
grep -c 'geneA' genes.fasta

# Mostrar solo la parte que coincide (-o)
grep -o 'gene[A-Z]' genes.fasta

1.4 Búsqueda recursiva y exclusiones

# Recursivo en subcarpetas
grep -R 'sample' .

# Excluir rutas por patrón
grep -R --exclude='*.fastq' 'gene' .

1.5 Expresiones regulares útiles (grep -E / -P)

# grep -E (ERE): alternancia con '|'
grep -E 'geneA|geneB' genes.fasta

# grep -E con anclas: encabezados FASTA (líneas que empiezan por '>')
grep -E '^>' genes.fasta

# grep -P (PCRE) para patrones más avanzados (si tu grep lo soporta)
grep -Pn '^\d{4}-\d{2}-\d{2}.*(ERROR|WARN)' app.log

1.6 Búsqueda en .gz sin descomprimir

# zgrep funciona como grep pero sobre .gz
gzip -c app.log > app.log.gz
zgrep 'ERROR' app.log.gz

Tip: Para búsquedas masivas y veloces, considera ripgrep (rg). Ejemplo: rg 'ERROR' -n .

2) sed: filtrar y sustituir texto en flujo

sed edita streams de texto: sustituye, elimina o imprime selectivamente.

2.1 Sustituciones básicas

# Cambiar 'WARN' por 'WARNING' (solo pantalla)
sed 's/WARN/WARNING/' app.log

# Edición in-place con respaldo
sed -i.bak 's/INFO/INFORMATION/' app.log

2.2 Eliminar o conservar líneas por patrón

# Eliminar líneas que contienen 'retry'
sed '/retry/d' app.log

# Quedarse solo con encabezados FASTA
sed -n '/^>/p' genes.fasta

2.3 Cambios por columnas (CSV sencillo)

# Reemplazar comas por tabs (vista rápida tipo TSV)
sed 's/,/\t/g' expr.csv | column -t

3) awk: procesar por campos y hacer cálculos

awk opera bajo la forma patrón { acción }, leyendo línea por línea y separando en campos ($1, $2, …).
Por defecto separa por espacios, pero podemos usar -F, para CSV o definir otro delimitador.

3.1 Filtrado y columnas (CSV)

Mostrar gene y counts cuando sample == "S2":

awk -F, 'NR>1 && $2=="S2"{print $1, $3}' expr.csv
  • F, → separador de campos = coma

  • NR>1 → ignora la cabecera

  • $2==“S2” → condición sobre la segunda columna

  • print $1, $3 → imprime columna 1 y 3

3.2 Resúmenes (sumas por clave)

Suma de counts por gene:

awk -F, 'NR>1{sum[$1]+=$3} END{for(g in sum) print g, sum[g]}' expr.csv | sort

sum[$1] guarda un acumulador por cada valor de gene.

3.3 Conteos en logs

Número de líneas con nivel ERROR en app.log:

awk '/ERROR/{c++} END{print "Total errores:", c}' app.log

Mostrar solo fecha y mensaje de los WARN:

awk '/WARN/{print $1, $2, $4, $5, $6}' app.log

3.4 Longitud de secuencias FASTA

(asumiendo que las secuencias están en una sola línea)

awk '
  /^>/ { if (seq) { print id, length(seq); seq="" } id=$0; next }
  { seq=seq$0 }
  END { if (seq) print id, length(seq) }
' genes.fasta

3.5 Porcentaje de GC en FASTA

awk '
  function gc(s){ gsub(/[^GCgc]/,"",s); return length(s) }
  /^>/ { 
    if (seq) { pct=100*gc(seq)/length(seq); printf "%s\t%.2f%%\n", id, pct; seq="" }
    id=$0; next 
  }
  { seq=seq$0 }
  END { if (seq) { pct=100*gc(seq)/length(seq); printf "%s\t%.2f%%\n", id, pct } }
' genes.fasta

3.6 Contar lecturas en FASTQ

awk 'END{print NR/4, "lecturas"}' reads.fastq

3.7 Promedio de calidad en FASTQ (simple)

awk '
  NR%4==1 { id=$0 }              # encabezado @SEQ_ID
  NR%4==0 {                      # línea de calidad
    sum=0; L=length($0)
    for(i=1;i<=L;i++){ sum+=ord(substr($0,i,1)) }
    printf "%s\t%.2f\n", id, sum/L
  }
  function ord(c){ return index(" !\"#$%&'\''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", c)-1 }
' reads.fastq

4) find y xargs: localizar archivos y operar sobre ellos

Cuando trabajamos con cientos de archivos, es esencial localizarlos y ejecutar operaciones en lote.
El comando find recorre directorios aplicando criterios de búsqueda, y se puede combinar con xargs o -exec para procesar resultados.

4.1 Búsqueda por nombre, tipo y tiempo

Sintaxis general:

find [directorio] [criterios] [acciones]

Ejemplo 1: buscar archivos .log

find . -type f -name "*.log"
  • . → buscar en el directorio actual.

  • -type f → solo archivos (no carpetas).

  • -name "*.log" → nombre que termina en .log.

Ejemplo 2: buscar archivos modificados en los últimos 7 días

find . -type f -mtime -7
  • -mtime -7 → archivos con menos de 7 días desde la última modificación.

  • Se pueden usar valores positivos (+7 = más de 7 días).

4.2 Ejecutar acciones sobre los resultados

Opción A: usando -exec

Contar líneas en cada archivo .fasta:

find . -type f -name "*.fasta" -exec wc -l {} \;
  • -exec comando {} \; → ejecuta un comando por cada archivo encontrado.

  • {} → se reemplaza con el nombre del archivo.

  • wc -l → cuenta líneas.

Opción B: usando xargs

Extraer encabezados FASTA (>) de todos los .fasta:

find . -type f -name "*.fasta" -print0 | xargs -0 grep -n '^>'
  • -print0 → imprime rutas terminadas en \0 (útil si hay espacios).

  • xargs -0 → lee esas rutas y las pasa como argumentos seguros.

  • grep -n '^>' → busca líneas que comienzan con > y muestra número de línea.

📌 Tip HPC: xargs -P ejecuta comandos en paralelo. Ejemplo: xargs -P4 lanza 4 procesos simultáneos.

5) Otras utilidades de texto

Linux ofrece herramientas ligeras que complementan grep/sed/awk.

5.1 cut: seleccionar columnas

Extraer gene y counts de un CSV:

cut -d, -f1,3 expr.csv | column -t -s,
  • -d, → separador es coma.

  • -f1,3 → mostrar columnas 1 y 3.

  • column -t -s, → alinea columnas para que se vea tabulado.

5.2 sort y uniq: ordenar y contar valores únicos

Contar cuántas veces aparece cada gene en el CSV:

cut -d, -f1 expr.csv | tail -n +2 | sort | uniq -c
  • cut -d, -f1 → toma solo la primera columna.

  • tail -n +2 → elimina encabezado (desde la línea 2).

  • sort → ordena los genes.

  • uniq -c → cuenta ocurrencias de cada valor.

5.3 head y tail: ver principio o final de archivos

head -n 3 app.log   # primeras 3 líneas
tail -n 2 app.log   # últimas 2 líneas

5.4 wc: contar líneas, palabras o caracteres

wc -l app.log       # número de líneas
wc -w app.log       # número de palabras
wc -c app.log       # número de caracteres (bytes)