HOWTO · Bash
Dividir cadena en variables en Bash
Esta es una descripción completa para dividir una cadena en variables en un script Bash.
En esta página
Para dividir una cadena delimitada en variables con nombre en Bash, elige un método que se adapte al delimitador: cut selecciona campos cuando hay un solo delimitador, read con IFS asigna los campos directamente y [[ ... =~ ... ]] captura campos mediante una expresión regular. Los ejemplos siguientes muestran cómo adaptar cada método y cuándo conviene usarlo.
Cadenas en Bash
Bash almacena texto en variables de cadena. Una cadena puede contener letras, dígitos, signos de puntuación y espacios; un delimitador es simplemente el carácter o la secuencia que eliges para separar sus campos. Por ejemplo, en blue:large:cotton, los dos puntos marcan tres campos. Bash no requiere una declaración de cadena independiente, así que asigna el texto con record="blue:large:cotton" y entrecomilla las expansiones de variables, como "$record", para conservar el valor como un único argumento.
Funciones de cadena en Bash
Este artículo se centra en dividir cadenas, no en las operaciones generales con ellas. La diferencia clave está entre seleccionar campos y buscar coincidencias con un patrón: cut selecciona campos numerados mediante un delimitador, IFS indica a read qué caracteres separan los campos y el operador =~ de Bash permite describir con una expresión regular las partes que se capturarán. Elige el método según si la entrada tiene un separador sencillo, varios caracteres separadores o una estructura que requiere un patrón.
Dividir una cadena en variables en Bash
Si el delimitador es sencillo, asigna los campos separados a variables con nombre. Este ejemplo autónomo usa cut para seleccionar tres campos separados por guiones y luego usa read para asignarlos. Las etiquetas visibles de la salida, como “First” y “Second”, permanecen en inglés:
record="0123-456-789"
fields=$(printf '%s\n' "$record" | cut -d '-' -f 1-3)
IFS='-' read -r first second third <<< "$fields"
printf 'First: %s\nSecond: %s\nThird: %s\n' "$first" "$second" "$third"
Usar el comando cut para dividir una cadena en variables en Bash
La opción -d del comando cut establece un único carácter delimitador, y -f selecciona uno o varios números de campo. En el ejemplo anterior, -f 1-3 indica a cut que seleccione los tres primeros campos. Capturar el resultado y pasarlo a read asigna esos campos a variables del shell. Entrecomilla la expansión de la entrada y usa printf para pasar el registro en una sola línea predecible.
Usa cut cuando los registros tengan un separador de un solo carácter constante y necesites seleccionar campos concretos. No trata varios delimitadores distintos como si fueran equivalentes y deja intacto el registro original. Si el delimitador no aparece, cut devuelve la línea sin cambios; por tanto, seleccionar campos no valida que el registro tenga la estructura esperada.
Usar un separador de campos interno (IFS) para dividir una cadena en variables en Bash
read divide su entrada usando IFS, el separador de campos interno. Establece IFS solo para ese comando para evitar alterar el comportamiento de división posterior del shell. Este ejemplo trata los guiones y las comas como separadores:
record="red-blue,green"
IFS='-,' read -r first second third <<< "$record"
printf 'First: %s\nSecond: %s\nThird: %s\n' "$first" "$second" "$third"
La opción -r conserva las barras invertidas como caracteres literales, mientras que entrecomillar "$record" protege la entrada. Cada carácter de IFS es un delimitador; no se trata de una cadena de varios caracteres que deba aparecer junta. Como los delimitadores de este ejemplo no son espacios en blanco, los separadores consecutivos pueden representar un campo vacío. Si indicas menos nombres de variables que campos, la última variable recibe el resto de la entrada, incluidos los separadores entre los campos restantes. De forma predeterminada, IFS contiene espacio, tabulación y salto de línea; read trata estos caracteres como separadores de espacios en blanco y los elimina de los extremos.
Usar read y sed para dividir una cadena en variables en Bash
Usa sed para transformar cada carácter coincidente en ese carácter seguido de un marcador y luego deja que read divida la entrada por ese marcador. A diferencia del método que usa los espacios en blanco predeterminados, este conserva los espacios de la cadena original:
record="A B!"
transformed=$(printf '%s' "$record" | sed 's/./&|/g')
IFS='|' read -r -a characters <<< "$transformed"
printf 'First: %s\nSecond: %s\nThird: %s\nFourth: %s\n' "${characters[0]}" "${characters[1]}" "${characters[2]}" "${characters[3]}"
Aquí, sed añade | después de cada coincidencia y read -a guarda los campos resultantes en un array indexado. El marcador solo es un separador que se introduce para esta transformación; no es una forma de propósito general para analizar registros estructurados. El significado de . en sed puede depender de la configuración regional activa, así que esta técnica es más adecuada para texto sencillo cuando ese comportamiento resulta aceptable. Un espacio insertado como separador se descartaría al tratarse como espacio en blanco por el IFS predeterminado; por eso este ejemplo elige | y establece IFS explícitamente.
Usar una expresión regular con coincidencias para dividir una cadena en variables en Bash
La condición [[ string =~ regex ]] de Bash comprueba si una cadena coincide con una expresión regular. Los grupos entre paréntesis están disponibles en BASH_REMATCH: el elemento cero contiene la coincidencia completa y los elementos a partir del uno contienen los grupos capturados. Mantén la expresión regular en una variable sin comillas a la derecha de =~ para que Bash la trate como un patrón:
record="31-28-31"
pattern='^([^-]+)-([^-]+)-([^-]+)$'
if [[ $record =~ $pattern ]]; then
first=${BASH_REMATCH[1]}
second=${BASH_REMATCH[2]}
third=${BASH_REMATCH[3]}
printf 'First: %s\nSecond: %s\nThird: %s\n' "$first" "$second" "$third"
fi
record="high,risk"
pattern='^([^,]+),([^,]+)$'
if [[ $record =~ $pattern ]]; then
first=${BASH_REMATCH[1]}
second=${BASH_REMATCH[2]}
printf 'First: %s\nSecond: %s\n' "$first" "$second"
fi
El primer patrón captura exactamente tres campos que no contienen guiones; el segundo captura dos valores separados por una coma. Ajusta los grupos si cambia el número o la estructura esperados de los campos. La coincidencia no está garantizada, así que coloca las asignaciones que usan BASH_REMATCH dentro de la rama que se ejecuta cuando hay una coincidencia. Este método resulta útil cuando hay que validar una regla de delimitación o capturar varias partes a la vez; para un delimitador fijo y sencillo, IFS o cut requieren menos código.