Limpiar una lista pegada desde una hoja de cálculo o un PDF
Publicado el 6/8/2026 · 12 min de lectura · Herramientas de texto e idioma
Daniel Okonkwo — Desarrollador front-end y redactor de Tecnología en OneKitly
Rendimiento web · Formatos de archivo
Verificado con 4 fuentes
Pasa primero trim-lines y después remove-blank-lines. El orden importa porque remove-blank-lines decide qué está vacío con el .trim() de JavaScript, que sí trata U+00A0 (espacio duro) como espacio, pero no toca el texto de las líneas que conserva: una línea «Lyon » sobrevive con sus tres espacios finales intactos. trim-lines usa ese mismo .trim() y limpia ambos extremos de cada línea, incluido un retorno de carro suelto. Entre los dos cubren espacios, tabulaciones, espacios duros, espacios finos y la marca de orden de bytes. Dos caracteres se les escapan: U+00AD, el guion opcional que un PDF inserta donde partió una palabra al final de la línea, y U+200B, el espacio de ancho cero. Ninguno es espacio para JavaScript, así que atraviesan remove-blank-lines, trim-lines, trailing-whitespace-remover y remove-whitespace sin cambios. Vigila sobre todo trailing-whitespace-remover: solo reconoce el espacio ASCII y el tabulador, de modo que sobre la cadena «x» seguida de un espacio duro no cambia nada, y sobre «x» + duro + espacio normal quita el normal y deja el duro. Las cuatro herramientas además reescriben en silencio los finales de línea CRLF como saltos simples, que suele ser lo deseado, y ninguna considera salto de línea un retorno de carro suelto. Un pegado desde una hoja de cálculo trae además tabulaciones entre las celdas de una fila: remove-whitespace con sus ajustes por defecto borrará esas tabulaciones y pegará tus columnas unas con otras.
Un pegado arrastra caracteres que no se ven: espacios duros, guiones opcionales, espacios de ancho cero, tabulaciones y CRLF. Se pasaron cuatro herramientas de limpieza por cada uno, y usan tres definiciones distintas de espacio.
Lo que llega de verdad al portapapeles
El texto que ves en pantalla y el texto del portapapeles no son el mismo objeto. Un PDF no tiene líneas ni párrafos: tiene cajas de glifos en coordenadas. Cuando seleccionas una columna de texto y la copias, el lector reconstruye un orden de lectura plausible e inserta un salto de línea al final de cada caja, de modo que una frase que ocupaba tres líneas impresas llega como tres líneas. Si el cajista partió una palabra en uno de esos finales, unos productores escriben un guion real y otros U+00AD, el guion opcional, que se dibuja como guion solo si allí cae un corte y como nada en caso contrario. Y como la mayoría de los PDF europeos se componen con espacios duros antes de los dos puntos, los puntos y comas y las unidades, un documento francés o italiano te entrega U+00A0 donde jurarías que hay espacios normales.
Un pegado desde una hoja de cálculo es más ordenado, pero no limpio. Excel, Numbers y Google Sheets ponen todos una tabulación entre las celdas de una fila y un salto de línea entre filas, y en Windows ese salto es un CRLF: un retorno de carro seguido de un avance de línea, dos caracteres donde ves uno. Borra un bloque de filas en medio de una selección y a menudo copias también las filas vacías, que llegan como líneas que solo contienen tabulaciones. Esa es justo la forma para la que están hechas las herramientas de esta página: una lista donde las líneas útiles están separadas por líneas que solo contienen caracteres invisibles, y donde algunas líneas útiles llevan caracteres invisibles propios en un extremo o en los dos.
Cuatro herramientas, tres definiciones de espacio
remove-blank-lines y trim-lines llaman ambos al .trim() de JavaScript. El lenguaje define lo que eso elimina como WhiteSpace más LineTerminator, y WhiteSpace incluye todos los caracteres de la categoría Unicode Space_Separator —donde viven U+00A0, U+2009 (espacio fino) y U+202F (espacio fino duro)— más la marca de orden de bytes U+FEFF. Pon cada uno de esos caracteres solo en una línea y pásalo por remove-blank-lines: la línea desaparece. remove-whitespace usa la clase de expresión regular \s, que designa el mismo conjunto. Tres de las cuatro herramientas coinciden, pues, sobre el espacio duro, y coinciden con lo que esperaría quien lee.
trailing-whitespace-remover no. Su patrón es una secuencia de espacio ASCII o tabulador anclada al final de la línea, y no cuenta nada más. Alimentado con la cadena x seguida de un espacio duro, devuelve la cadena sin cambios. Alimentado con x seguido de un duro y luego de un espacio normal, quita el normal y devuelve x más el duro: visualmente no ha acortado nada, y sigue sin ser igual a x. No es una diferencia cosmética. Si limpias una lista antes de quitarle duplicados, ese espacio duro superviviente es lo que mantiene separados dos nombres de ciudad idénticos.
Los dos caracteres que ninguna de estas herramientas elimina
U+00AD, el guion opcional, y U+200B, el espacio de ancho cero, no son espacios para JavaScript. La clase de expresión regular \s no los reconoce y .trim() no los elimina, lo cual se comprobó directamente en vez de darlo por hecho. Así que una línea que solo contiene un guion opcional sobrevive a remove-blank-lines y parece, en el cuadro de salida, exactamente una línea vacía que la herramienta se ha negado a borrar. La palabra «cooperativas» copiada de un PDF con partición, con un guion opcional entre «co» y «operativas», sale idéntica de las cuatro herramientas, y nunca coincidirá con la cadena «cooperativas» en ninguna búsqueda que hagas después.
Hay una sola herramienta en este sitio que sí los borra, y el trato es malo para cinco de nuestros seis idiomas. remove-non-ascii quita todo carácter por encima de U+007F, lo que sí se lleva el guion opcional, el espacio de ancho cero, el espacio duro y la marca de orden de bytes. También se lleva sin más cada letra acentuada en vez de plegarla: la frase «Les coopératives régionales», pasada con un guion opcional dentro de la primera palabra, salió como «Les coopratives rgionales» — la e acentuada simplemente desaparecida, no sustituida por una sin acento. La vía honesta es find-and-replace con el carácter culpable pegado en el campo «Buscar», que funciona porque esa herramienta escapa su término de búsqueda y lo compara literalmente. Eso sí, hay que conseguir una copia de un carácter invisible, lo cual es exactamente tan incómodo como suena.
Finales de línea, y el único salto que estas herramientas no ven
Las cuatro herramientas dividen por un avance de línea precedido de un retorno de carro opcional, y luego reúnen el resultado con avances simples. Eso significa que todas normalizan los finales CRLF de Windows a saltos Unix como efecto secundario, hagas lo que hagas además: pega un bloque de hoja de cálculo, pasa remove-blank-lines, y la salida es un byte más corta por fila aunque no se haya eliminado ninguna línea. Casi siempre es lo que querías, pero conviene saber que ha ocurrido, porque un archivo que después tenga que volver a una herramienta de Windows quizá necesite que le devuelvan sus finales.
El salto que no ven es un retorno de carro solo, sin avance de línea detrás: el final de línea del Mac OS clásico hasta 2001, y el que aún emiten algunas rutinas de exportación antiguas y ciertos volcados de bases de datos. Ante los tres caracteres a, retorno de carro, retorno de carro, b, las cuatro herramientas tratan el conjunto como una sola línea y lo devuelven intacto. Nada te avisa. Si un pegado vuelve como una única línea enorme sin saltos visibles y sin error, eso es lo primero que hay que sospechar, y el remedio es abrir el archivo en un editor capaz de convertir finales de línea antes de traerlo aquí.
El orden en que encadenarlas
trim-lines primero, remove-blank-lines después. El orden inverso da el mismo resultado en la mayoría de las entradas, porque remove-blank-lines ya prueba cada línea con .trim() antes de decidir: una línea de tres espacios cae hayas recortado antes o no. Se comprobó sobre la entrada desordenada «dos espacios, alpha, dos espacios», luego una línea solo de tabulador, luego «dos espacios, beta, un espacio», luego una línea vacía, luego «alpha»: ambos órdenes produjeron alpha, beta, alpha. La razón para poner trim-lines primero de todos modos es lo que viene después. Dale esa misma entrada a duplicate-line-finder sin recortarla y no señala ningún duplicado, porque el primer alpha lleva dos espacios delante y dos detrás. Dale la versión recortada y señala alpha.
Dos cosas que no hacer. No eches mano de remove-whitespace sobre un pegado de hoja de cálculo si no has decidido que las columnas pueden desaparecer: con su ajuste por defecto elimina todo espacio, tabulador y salto de línea, y la fila de cabecera «Nom, tabulador, Ville, tabulador, CA» salió como «NomVilleCA». Activar «mantener saltos de línea» conserva las filas pero sigue comiéndose los tabuladores, así que las columnas siguen pegadas. Y no pases trailing-whitespace-remover esperando que haga comparables dos líneas: quita el espacio ASCII y el tabulador, y nada más, que era todo el asunto de la segunda sección. Cuando el objetivo es comparar y no ordenar, trim-lines es la que cierra la brecha.
| Entrada | Qué pasa | Por qué |
|---|---|---|
| Una línea de tres espacios normales, en remove-blank-lines | Eliminada | La prueba es línea.trim().length > 0, y .trim() la vacía |
| Una línea que solo contiene U+00A0, en remove-blank-lines | Eliminada | El WhiteSpace de ECMAScript cubre toda la categoría Space_Separator |
| Una línea que solo contiene U+00AD, en remove-blank-lines | Conservada, y parece vacía en la salida | El guion opcional es de categoría Cf, un carácter de formato, no un espacio |
| x seguido de un U+00A0, en trailing-whitespace-remover | Devuelto sin cambios | Su patrón es una secuencia de espacio ASCII o tabulador al final de línea, nada más amplio |
| x, luego U+00A0, luego un espacio normal, en trailing-whitespace-remover | Vuelve como x seguido de U+00A0 | La secuencia de espacios ASCII se detiene en el primer carácter fuera de la clase |
| El mismo x más U+00A0, en trim-lines | Vuelve como x | El mismo .trim() que remove-blank-lines, aplicado al texto en vez de a la prueba |
| La fila de cabecera Nom, tabulador, Ville, tabulador, CA, en remove-whitespace | NomVilleCA — las columnas han desaparecido | Un tabulador es espacio, y «mantener saltos de línea» solo perdona el salto de línea |
| a, retorno de carro, retorno de carro, b — en cualquiera de las cuatro | Tratado como una sola línea, devuelto intacto | Todas dividen por un avance de línea precedido de un retorno de carro opcional |
Preguntas frecuentes
- ¿Por qué mi lista sigue teniendo líneas que parecen vacías después de remove-blank-lines?
- Casi con seguridad es un espacio de ancho cero (U+200B) o un guion opcional (U+00AD) solo en la línea. Ninguno es espacio para JavaScript, así que la prueba de la herramienta —¿queda algo tras .trim()?— responde que sí y la línea permanece. Ambos se pasaron por la herramienta para confirmarlo. Un espacio duro o un espacio fino solos sí se habrían eliminado, de modo que la línea superviviente no es uno de esos. Para identificar el carácter sin adivinar, pega la línea en un contador de caracteres o de bytes y comprueba que la cuenta es uno y no cero.
- Entonces, ¿trailing-whitespace-remover está roto?
- Hace lo que dice su propia descripción —eliminar los espacios y tabuladores finales— y esa definición estrecha es la correcta para su trabajo habitual: limpiar la basura invisible al final de las líneas de código antes de un commit. Las herramientas de diff y los linters se ocupan del espacio ASCII y del tabulador; un espacio duro dentro de código es un error que quieres ver, no uno que quieras borrar en silencio. El único problema es que el nombre se lee como una promesa general. Para prosa y para listas pegadas desde documentos, trim-lines es la herramienta de definición amplia, y es la que hay que usar cuando dos líneas deben compararse iguales después.
- ¿Cómo me deshago de los guiones opcionales que un PDF ha metido en mi texto?
- Ninguna de las cuatro herramientas de este artículo lo hará. find-and-replace sí, si consigues meter un guion opcional en su campo «Buscar»: la herramienta escapa lo que escribas y lo compara literalmente, cosa comprobada, así que pegar el carácter funciona y escribir una descripción de él no. Conseguir una copia de un carácter invisible suele pasar por seleccionar un hueco sospechosamente ancho en el texto original con las flechas y Mayús, y copiarlo. remove-non-ascii también los elimina, pero se lleva con ellos cada letra acentuada sin sustituirla: sobre texto francés, español, portugués, alemán o italiano destruye más de lo que arregla.
- ¿Algo de esto envía mi lista a un servidor?
- No. Las cuatro transformaciones son operaciones de cadena corrientes que se ejecutan en la página que tienes abierta, sobre el texto del cuadro, y producen su salida en la misma página. Nada en la naturaleza del trabajo exige un servidor: dividir por saltos de línea y probar cada línea son unas pocas líneas de código, y no hay diccionario ni modelo que consultar. Aquí importa más de lo habitual, porque las listas que se limpian así suelen salir de documentos internos —nombres de clientes, referencias de pedidos, plantillas de personal— y pegar una en una herramienta que la sube es una decisión de transferencia de datos, no de formato.
- Mi pegado de hoja de cálculo conserva los tabuladores. ¿Cómo obtengo un elemento por línea?
- Ninguna de las cuatro hace eso, y remove-whitespace hace justo lo contrario: borra los tabuladores y suelda las celdas entre sí, cosa comprobada sobre una fila de cabecera de tres columnas que volvió como una sola palabra. Si solo querías una columna, copia una sola columna de la hoja: el pegado no contendrá tabulador alguno y remove-blank-lines más trim-lines bastan. Si tienes varias columnas y las quieres apiladas una por línea, esa es otra operación con su propia herramienta, y la respuesta honesta es que estas cuatro limpian líneas, no parten columnas.
Artículos que podrían interesarte
Todas las guías →Herramientas relacionadas
Todo lo que sigue describe lo que hacen estas herramientas hoy, comprobado ejecutando sus propias transformaciones sobre las entradas exactas que aparecen en cada artículo, y no lo que una norma obligue a hacer a una herramienta de texto. El tratamiento del texto línea a línea no tiene una autoridad única: qué cuenta como espacio, si dos líneas acentuadas son o no la misma línea, y dónde termina una URL dentro de una frase se deciden de forma distinta en cada programa en el que pegues texto. Cuando una herramienta falla en un caso, se dice claramente en vez de esquivarlo. Antes de pasar nada de esto por una lista que no puedas volver a exportar, pásalo por una copia y compara el número de líneas en ambos extremos.
Fuentes
- Ecma International — ECMAScript Language Specification — WhiteSpace and String.prototype.trim
- Unicode Consortium — Unicode Character Database — PropList.txt (White_Space property)
- Unicode Consortium — UAX #14: Unicode Line Breaking Algorithm (soft hyphen, class BA)
- MDN Web Docs — Regular expressions — character class escape (\s)
¿Has detectado un error en este artículo?