arrays - loop - linux shell define array
Crear una matriz a partir de un archivo de texto en Bash (6)
Use mapfile o lea -a
Siempre revise su código usando shellcheck . A menudo le dará la respuesta correcta. En este caso, SC2207 cubre la lectura de un archivo que tiene valores separados por espacio o por línea nueva en una matriz.
No hagas esto
array=( $(mycommand) )
Archivos con valores separados por líneas nuevas
mapfile -t array < <(mycommand)
Archivos con valores separados por espacios
IFS=" " read -r -a array <<< "$(mycommand)"
La página de shellcheck le dará la razón por la cual esto se considera la mejor práctica.
Un script toma una URL, la analiza para los campos obligatorios y redirige su salida para guardarla en un archivo, file.txt . La salida se guarda en una nueva línea cada vez que se encuentra un campo.
file.txt
A Cat
A Dog
A Mouse
etc...
Quiero tomar
file.txt
y crear una matriz a partir de él en un nuevo script, donde cada línea se convierta en su propia variable de cadena en la matriz.
Hasta ahora he intentado:
#!/bin/bash
filename=file.txt
declare -a myArray
myArray=(`cat "$filename"`)
for (( i = 0 ; i < 9 ; i++))
do
echo "Element [$i]: ${myArray[$i]}"
done
Cuando ejecuto este script, el espacio en blanco hace que las palabras se dividan y en lugar de obtener
Salida deseada
Element [0]: A Cat
Element [1]: A Dog
etc...
Termino obteniendo esto:
Salida real
Element [0]: A
Element [1]: Cat
Element [2]: A
Element [3]: Dog
etc...
¿Cómo puedo ajustar el bucle a continuación de modo que toda la cadena en cada línea corresponda uno a uno con cada variable en la matriz?
Simplemente puede leer cada línea del archivo y asignarla a una matriz.
#!/bin/bash
i=0
while read line
do
arr[$i]="$line"
i=$((i+1))
done < file.txt
También puedes hacer esto:
oldIFS="$IFS"
IFS=$''/n'' arr=($(<file))
IFS="$oldIFS"
echo "${arr[1]}" # It will print `A Dog`.
Nota:
La expansión del nombre de archivo todavía ocurre.
Por ejemplo, si hay una línea con un literal
*
, se expandirá a todos los archivos en la carpeta actual.
Úselo solo si su archivo está libre de este tipo de escenario.
Use el comando
mapfile
:
mapfile -t myArray < file.txt
El error se usa
for
: la forma idiomática de recorrer las
líneas
de un archivo es:
while IFS= read -r line; do echo ">>$line<<"; done < file.txt
Ver BashFAQ/005 para más detalles.
Esta respuesta dice usar
mapfile -t myArray < file.txt
Hice una
shim
para
mapfile
si desea usar
mapfile
en bash <4.x por cualquier razón.
Utiliza el comando
mapfile
existente si está en bash> = 4.x
Actualmente, solo funcionan las opciones
-d
y
-t
.
Pero eso debería ser suficiente para ese comando anterior.
Solo lo he probado en macOS.
En macOS Sierra 10.12.6, el bash del sistema es
3.2.57(1)-release
.
Entonces la cuña puede ser útil.
También puede actualizar su bash con homebrew, construir bash usted mismo, etc.
Utiliza esta técnica para configurar variables en una pila de llamadas.
mapfile
y
readarray
(que son sinónimos) están disponibles en Bash versión 4 y superior.
Si tiene una versión anterior de Bash, puede usar un bucle para leer el archivo en una matriz:
arr=()
while IFS= read -r line; do
arr+=("$line")
done < file
En caso de que el archivo tenga una última línea incompleta (falta una nueva línea), puede usar esta alternativa:
arr=()
while IFS= read -r line || [[ "$line" ]] do
arr+=("$line")
done < file
Relacionado: