Mostrar caracteres no imprimibles en un archivo de texto

A veces los archivos de texto contienen caracteres no imprimibles o espacios al final de línea que no siempre se notan claramente.

$ cat contenido.txt
texto 1
texto 2
texto   3

Invocando cat con la opción -A podemos verlos:

$ cat -A contenido.txt
texto 1 ^M$
texto 2^M$
texto^I3^M$
^M$

En este ejemplo podemos, se trata de un archivo en formato DOS por el fin de línea utilizado (^M$), en el cual:

  • la primer línea tiene un espacio luego de 1,
  • la tercera tiene un TAB (^I) entre texto y 3
  • la última es una línea vacía

Basado en:

http://systemadmin.es/2015/03/ver-caracteres-no-imprimibles-con-cat

Anuncios

Tratamiento de mayúsculas y minúsculas en MySQL

Según Wikipedia, la sensibilidad a mayúsculas y minúsculas, se explica de la siguiente manera:

Que algo sea sensible a las mayúsculas y minúsculas, abreviado a veces como sensible a mayúsculas,​ y dicho también directamente en inglés case sensitive, es una expresión usada en informática que se aplica a los textos en los que tiene alguna relevancia escribir un carácter en mayúsculas o minúsculas.

Lo contrario se denomina insensible a las mayúsculas y minúsculas, abreviado a veces como insensible a mayúsculas​ y dicho también directamente en inglés case insensitive.

 

Por defecto, MySQL hace un tratamiento diferente para las mayúsculas en los nombres de las bases de datos y tablas según el sistema operativo como veremos a continuación.

Lo más sencillo y recomendable para facilitar el uso, la portabilidad y evitar problemas es adoptar una convención consistente: crear y consultar bases de datos y tablas usando nombres en minúsculas.

Muchas veces no se puede aplicar esta recomendación “de palabra”, por lo que se debe recurrir a una variable de configuración.

 

Variable lower_case_table_names

Esta variable se define dentro del archivo de configuración my.cnf (Linux) o my.ini (Windows). Determina cómo MySQL almacena en disco y consulta los nombres de bases de datos y tablas. El almacenamiento en disco se refiere al proceso de creación, con las instrucciones CREATE DATABASE y CREATE TABLE, respectivamente.

  • lower_case_table_names=0 (case sensitive en la creación y consulta)
    • los nombres se guardarán en disco tal y como se han especificado en la creación
    • los nombres en las consultas deben respetar las mayúsculas
    • NO de se debería establecer en sistemas operativos que sean case-insensitive! (Windows u OS X)
  • lower_case_table_names=1 (case insensitive en la creación y consulta)
    • los nombres se guardarán en disco siempre en minúsculas, independientemente de como se escriban
    • los nombres en las consultas son convertidos a minúsculas (también aplica a los aliases)
  • lower_case_table_names=2 (case sensitive en la creación – case insensitive en la consulta)
    • los nombres se guardarán en disco tal y como se han especificado en la creación
    • los nombres en las consultas son convertidos a minúsculas (también aplica a los aliases)
    • Solo funciona en sistemas operativos que no sean case-sensitive!
    • Los nombres de tablas InnoDB son una excepción y se almacenan en minúsculas, como en el caso de lower_case_table_names=1

A continuación, los valores por defecto para cada sistema operativo:

  • Linux: lower_case_table_names=0
  • Windows: lower_case_table_names=1
  • OS X: lower_case_table_names=2

 

¿Qué valor de lower_case_table_names usar?

En el caso de usar MySQL en un solo tipo de sistema operativo, se puede mantener el valor por defecto de lower_case_table_names.

Los conflictos aparecen al empezar a transferir tablas hacia otros sistemas que difieran en la sensibilidad a mayúsculas:

En Linux podrían existir las siguientes tablas: usuarios, USUARIOS y Usuarios.

Al importar un dump que las contuviera en Windows, la primera se crea sin problemas, pero la siguiente genera un error indicando que la tabla ya existe. Esto sucede porque para Windows las 3 tienen el mismo nombre.

A fin de evitar este tipo de problemas se puede optar por:

  1. Usar lower_case_table_names=1 en todos los sistemas (mi recomendación)
    • La “desventaja” es que no se verán listados con sus nombres originales, si los mismos estaban especificados con mayúsculas en la creación
  2. Usar lower_case_table_names=0 en Linux y lower_case_table_names=2 en Windows.
    • Esta alternativa es propensa a fallar cuando se hagan consultas que funcionan en Windows porque los nombres se pasan a minúsculas automáticamente, pero en Linux generan errores porque no se utilizaron las mayúsculas tal cual se especificaron en la creación.
    • Si se usan tablas InnoDB no queda más remedio que usar la opción 1.

 

Basado en:

http://rm-rf.es/mayusculas-y-minusculas-en-mysql/

Concatenar cadenas de caracteres en MySQL

La función más común para juntar un conjunto de cadenas de caracteres en MySQL es CONCAT(cadena1, cadena2, …)

Algunas consideraciones:

  • Si los argumentos que recibe son “no binarios”, la cadena resultante es no binaria
  • Si al menos uno de los argumentos es una cadena binaria, la salida es binaria.
  • Un número se convierte a su forma de texto no binaria
  • Si alguno de los argumentos es NULL, retorna NULL

mysql> SELECT CONCAT('Lalo', ' ' , 'Landa');
-> 'Lalo Landa'

mysql> SELECT CONCAT('Lalo', NULL , 'Landa');
-> NULL

El uso más común es para unir nombre de campos de las tablas incluidas en la consulta:

mysql> SELECT CONCAT(apellido, ', ' , nombre) FROM usuarios;
-> 'Gómez, Mario'

Cuando es necesario indicar un separador para unir más de 2 cadenas, lo recomendable es usar la función CONCAT_WS(separador, cadena1, cadena2, …)

Es una forma especial de CONCAT(). El WS al final proviene de  “With Separator”, lo que en conjunto sería “Conctatenar con Separador”. El primer argumento que recibe es el separador que se agregará entre cada una de las cadenas indicadas a continuación.

Algunas consideraciones:

  • Si el separador es NULL, el resultado es NULL
  • Si alguno de las cadenas es NULL, la misma se omite

mysql> SELECT CONCAT_WS(' ', 'Lalo' , 'Landa');
-> 'Lalo Landa'

mysql> SELECT CONCAT_WS(' ', 'Lalo', NULL , 'Landa');
-> 'Lalo Landa'

Concatenando múltiples campos:

mysql> SELECT CONCAT(' ', titulo, nombre, apellido) FROM usuarios;
-> 'Ing. Sergio Morales'

Almacenamiento de caracteres en MySQL

En Mysql, los caracteres se almacenan en los campos de tipo CHAR y VARCHAR.

CHAR

  • Tiene una longitud fija (máxima), entre 0 y 255, desde el momento en que se agrega a la tabla.
  • Cuando se guarda un valor, se agregan espacios al final hasta completar la longitud.
  • Cuando se obtiene el valor, los espacios al final se quitan (excepto que esté activado el modo sql PAD_CHAR_TO_FULL_LENGTH)
  • Los espacios finales en exceso en valores insertados son truncados silenciosamente.

VARCHAR

  • Tiene una longitud variable siendo la máxima, entre 0 y 65536.
  • Los valores se almacenan con un prefijo de 1 byte si la longitud es hasta 255 bytes y de 2 bytes si es mayor, además de los datos.
  • Los valores no se completan con espacios cuando se guardan.
  • Los espacios al final se guardan y se obtienen siempre.
  • Los espacios finales que exceden la longitud máxima se truncan antes de la inserción y generan un warning.

En ambos tipos

  • Si no está activado el modo estricto, al asignar un valor a un campo CHAR o VARCHAR que excede su longitud máxima, se trunca y genera un warning. Caso contrario, se genera un error y se anula la consulta.
  • Los valores se ordenan y comparan de acuerdo al collation asociado al campo.
  • Los valores se comparan omitiendo los espacios finales, a excepción de cuando se usa el operador LIKE, para el cual importan los espacios al final.
  • Si un campo tiene un índice que requiere valores únicos, al insertar valores que solamente difieran en los espacios al final se generará un error de duplicate key.

Consultas de textos case sensitive en MySQL

Mysql es por defecto case insensitive (no sensible a las mayúsculas): no diferencia las mayúsculas de las minúsculas. Esto se debe a que tiene configurado inicialmente el collation ‘latin1_swedish_ci’.

mysql> SELECT nombre_usuario FROM usuarios WHERE nombre_usuario LIKE 'al%'; # retorna usuarios con nombres como 'Alberto', 'Álvaro', 'alejo'

Por lo general, cuando hacemos una comparación es muy conveniente este comportamiento dado que no importa la capitalización que usemos, encontraremos los resultados.

 

Tengamos en cuenta que para los campos con caracteres no binarios: CHAR, VARCHAR y TEXT, la comparación depende del collation de los mismos.

En cambio, para los campos binarios: BINARY, VARBINARY y BLOB se utiliza el valor numérico de los bytes en la comparación, por lo que serán case sensitive en el caso de los caracteres.

Si se compara una cadena binaria y una no-binaria, la comparación se realiza como si fueran ambas binarias.

 

Pero en ciertos casos, cuando deseamos comparar los caracteres contemplando su capitalización, podemos optar por alguna de las siguientes alternativas:

  • Usar el operador COLLATE para indicar un collation que sea case sensitive (termina con _cs o _bin)  que pertenezca al juego de caracteres correspondiente a un campo, un valor o a ciertas partes de la consulta.
    • Disponible a partir de Mysql 4.1
  • Usar el operador BINARY sobre el valor o columna en la consulta
  • Cambiar  el collation de la columna CHAR(N), VARCHAR(N) o TEXT mediante un ALTER TABLE por uno que sea case sensitive:
    • agregando BINARY al final, lo cual especifica el collation _bin para el juego de caracteres correspondiente
    • indicando el CHARSET y COLLATION específicos
  • Cambiar el tipo de dato de la columna mediante un ALTER TABLE por uno que sea case sensitive:
    • BINARY, VARBINARY o BLOB

Ejemplos de uso de COLLATE

mysql> SELECT nombre_usuario FROM usuarios WHERE nombre_usuario LIKE 'Al%' COLLATE latin1_spanish_cs; # retorna usuarios con nombres como 'Alberto' o 'Álvaro'. NO 'alejo'

mysql> SELECT nombre_usuario FROM usuarios WHERE nombre_usuario COLLATE latin1_bin LIKE 'al%'; # retorna usuarios con nombres como 'alejo'. NO 'Alberto' ni 'Álvaro'

 

Sabiendo también cómo cambiar el tipo de dato a un valor o a un campo, podemos notar que todas las expresiones son equivalentes cuando se utilizan en una comparación:

CAST(nombre AS BINARY) = CONVERT(nombre,BINARY) = BINARY nombre = nombre COLLATE latin1_bin

COLLATE no cambia el tipo de dato, solo aplica un collation al momento de usar el campo en una comparación

Cambiar el tipo de un valor en MySQL

Las formas de cambiar el tipo de un valor o un campo en una consulta son las siguientes:

Operador BINARY

Transforma un texto a una cadena binaria.

Una cadena binaria contiene bytes en lugar de caracteres, lo que la hace case sensitive cuando se utiliza para una comparación. Adicionalmente los espacios al final se vuelven significativos.

mysql> SELECT 'Nombre' = 'nombre'; # retorna 1

mysql> SELECT BINARY 'Nombre' = 'nombre'; # retorna 0

Se puede aplicar CAST para obtener el mismo resultado

BINARY texto = CAST(texto AS BINARY)

Importante: Si la columna sobre la que se aplica BINARY está indexada, Mysql podría no utilizar el índice en esa consulta!

 

Funciones CONVERT y CAST

Convierten una expresión de un tipo en otro.

La forma de aplicarlas es la siguiente:

CONVERT(expresión,tipo)

CAST(expresión AS tipo)

donde tipo puede ser:

  • BINARY[(N)]
    • El parámetro opcional (N) hace que no se usen más de N bytes en la conversión
      • Desde Mysql 5.0.7, los textos menores a N bytes son completados con bytes 0x00 hasta la longitud N.
  • CHAR[(N)]
    • El parámetro opcional (N) hace que no se usen más de N caracteres en la conversión
    • Trata la expresión como una cadena con el conjunto de caracteres por defecto.
  • DATE
  • DATETIME
  • DECIMAL[(M[,D])]
    • Disponible desde Mysql 5.0.8
  • SIGNED [INTEGER]
  • TIME
  • UNSIGNED [<ENTERO>]

mysql> SELECT CONVERT('2014-01-01',DATETIME); # retorna 2014-01-01 00:00:00

mysql> SELECT CAST('150 usuarios' AS UNSIGNED); # retorna 150

Escapar caracteres en línea de comandos de Windows

En la línea de comandos de Windows hay ciertos caracteres que tienen un comportamiento especial:

\ & ^ | > <

Cuando necesitamos escribirlos como texto simple debemos anteponerle el caracter de escape ^.

Entonces, cada uno de los especificados anteriormente, quedarían:

^\ ^& ^^ ^| ^> ^<

Para dar un ejemplo de uso, podemos querer listar los archivos de texto que contengan un signo &:

dir *^&*.txt