HOWTO · Bash
Extraer subcadena en Bash
Este tutorial demuestra diferentes formas de extraer una subcadena en bash usando el comando cut, la expansión de la subcadena y el Separador de campo interno.
En esta página
Para obtener una parte de una cadena en Bash, elige la operación que corresponda a la entrada: cut selecciona un campo separado por un delimitador, la expansión de subcadenas de Bash selecciona caracteres por posición y la división con IFS convierte el texto delimitado en campos que puedes procesar por separado. Estos métodos están relacionados, pero no devuelven los datos de la misma manera.
Extraer un campo delimitado con cut
Usa cut cuando el valor tenga un delimitador constante y quieras obtener un campo específico. La opción -d establece el delimitador y -f selecciona el número de campo, que empieza en uno. En este ejemplo, las palabras están separadas por guiones bajos, así que el campo 3 es three. Pon entre comillas la expansión de la variable y pásala a printf; así el valor se mantiene en una sola línea de entrada y se evita la forma insegura sin comillas echo $numbers.
Ejecuta este ejemplo. La etiqueta substring y el valor que muestra se mantienen en inglés en los bloques inmutables; la etiqueta identifica el valor extraído.
numbers='one_two_three_four_five'
substring=$(printf '%s\n' "$numbers" | cut -d '_' -f 3)
printf 'substring: %s\n' "$substring"
substring: three
cut selecciona campos, no un rango arbitrario de caracteres. Es una buena opción para texto estructurado cuyo delimitador y posiciones de campo se conocen; si el rango deseado depende de la posición de los caracteres, usa en su lugar la expansión de subcadenas.
Extraer caracteres con la expansión de subcadenas de Bash
Bash permite expandir una subcadena con la forma ${variable:offset:length}. El desplazamiento empieza en cero y la longitud indica cuántos caracteres se devuelven. Por ejemplo, en one_two_three_four_five, el desplazamiento 4 empieza en la t de two, y la longitud 3 selecciona esos tres caracteres. Para calcular el desplazamiento, cuentan todos los caracteres de la cadena original, incluidos los delimitadores.
Ejecuta este ejemplo. La etiqueta substring y el valor que muestra se mantienen en inglés en los bloques inmutables; la etiqueta identifica el valor extraído.
numbers='one_two_three_four_five'
substring=${numbers:4:3}
printf 'substring: %s\n' "$substring"
substring: two
Esta es la opción directa cuando conoces la posición y el rango de caracteres. El desplazamiento no es un número de campo: si cambia la longitud del texto anterior a la parte deseada, el mismo desplazamiento puede seleccionar otros caracteres. Para un valor separado en campos con nombre o numerados, suele ser más fácil adaptar cut o IFS.
Dividir una cadena en campos con IFS
IFS es el separador interno de campos de Bash. Controla la división en palabras después de una expansión sin comillas y también afecta a cómo el comando integrado read divide la entrada. Un valor temporal de IFS permite dividir una cadena delimitada en parámetros posicionales. $1, $2 y $3 se refieren al primer, segundo y tercer parámetro; no son una sintaxis para índices de arrays.
El ejemplo limita la división a una función y desactiva la expansión de rutas antes de usar la expansión sin comillas. Esto es importante porque, después de dividir las palabras, se expanden los nombres de ruta: si un campo contiene *, ? o un patrón entre corchetes, el shell podría sustituirlo por nombres de archivo coincidentes. Usa esta forma con entradas controladas y un delimitador conocido. Si el delimitador no es un espacio en blanco, establece IFS con ese delimitador y lee la entrada en un array con read -a; después, usa entre comillas las expansiones del array al acceder a los campos. Con el valor predeterminado de IFS, los espacios, tabuladores y saltos de línea separan los campos; si cambias IFS por un delimitador, la entrada se divide por ese delimitador. Este método no conserva los campos que contienen el delimitador elegido, y el read -a orientado a líneas no puede conservar los saltos de línea incrustados dentro de un campo. Para esos formatos, usa un analizador diseñado para el formato en lugar de depender únicamente de read -a.
Ejecuta este ejemplo. La etiqueta second field y el valor que muestra se mantienen en inglés en los bloques inmutables; la etiqueta identifica el segundo campo.
numbers='one_two_three_four_five'
extract_second() (
local IFS=_
set -f
set -- $numbers
printf 'second field: %s\n' "$2"
)
extract_second
second field: two
Dentro de la función, set -- reemplaza sus parámetros posicionales por los campos divididos; al salir de la función, se restauran los parámetros posicionales de quien la llamó. El separador local no cambia de forma permanente el IFS del script.
Elegir el método adecuado
Elige cut para seleccionar un campo numerado de un texto con un delimitador conocido, como el tercer valor separado por guiones bajos. Elige la expansión de subcadenas de Bash para obtener caracteres a partir de un desplazamiento y una longitud conocidos, con desplazamiento desde cero. Elige la división con IFS cuando necesites convertir los campos en palabras del shell o parámetros posicionales para procesarlos después.
Con una entrada predecible, cada opción es concisa. Mantén entre comillas la entrada de cut, usa llaves en la expansión de subcadenas y recuerda que la expansión sin comillas para dividir con IFS también puede activar la expansión de rutas. Si el delimitador forma parte de los datos o los campos pueden contener caracteres de patrón del shell, usa un método de análisis que conserve los campos como elementos de array entre comillas en vez de depender de la división de palabras sin comillas. Esta distinción ayuda a evitar tratar como equivalentes el número de un campo, el desplazamiento de un carácter y un parámetro posicional como formas de «subcadena».