BASH leyendo un archivo txt y almacenándolo en una matriz

Estoy escribiendo mi primer script BASH, tengo algo de experiencia con cy c #, así que creo que la lógica del El programa es correcto … es solo que la sintaxis es muy complicada porque aparentemente hay miles de millones de formas de escribir lo mismo.

De todos modos, aquí está el script: simplemente verifica si el argumento (cadena) es contenido en un determinado archivo. Si es así, almacena cada línea del archivo en una matriz y escribe un elemento de la matriz en un archivo. Estoy seguro de que debe haber formas más fáciles de lograr eso, pero quiero practicar un poco con los bucles bash

 #!/bin/bash NOME=$1 c=0 #IF NAME IS FOUND IN THE PHONEBOOK THANK STORE EACH LINE OF THE FILE INTO ARRAY #ONCE THE ARRAY IS DONE GET THE INDEX OF MATCHING NAME AND RETURN ARRAY[INDEX+1] if grep "$NOME" /root/phonebook.txt ; then echo "CREATING ARRAY" while read line do myArray[$c]=$line # store line c=$(expr $c + 1) # increase counter by 1 done < /root/phonebook.txt else echo "Name not found" fi c=0 for i in myArray; do if myArray[$i]="$NOME" ; then echo ${myArray[i+1]} >> /root/numbertocall.txt fi done 

Este código devuelve el único segundo elemento de myArray (myArray[2] o la segunda línea del archivo) … ¿por qué?

Comentarios

  • ¿Qué relevancia tiene \ t? Tanto el texto como el resto del código solo se refieren a líneas.
  • No es una respuesta directa, por lo que ' es solo una comentario, pero ' hago esto con un grep de una línea; grep -P -o "(?<=$NOME\t).+"
  • @Patrick Classic Problema XY , así que creo que tu comentario debería ser una respuesta. Después de todo, hace lo correcto.

Respuesta

IFS=$"\n" a=($(cat phonebook.txt)) for i in $(seq ${#a[*]}); do [[ ${a[$i-1]} = $name ]] && echo "${a[$i]}" done 

En Bash 4 IFS=$"\n" a=($(cat phonebook.txt)) se puede reemplazar por mapfile -t a < phonebook.txt.

grep -A1 imprime una línea después de la coincidencia. -x deshabilita expresiones regulares como -F pero solo coincide con la l completa ines.

grep -x "$name" -A1 phonebook.txt | tail -n1 

Comentarios

  • Puede querer validar el el contenido del archivo primero. Depende de usted.
  • -x no deshabilita la expresión regular .
  • Dejando que $(cat phonebook.txt) sin comillas en ese contexto de lista invoca split + glob en la expansión. Aquí, desea la parte dividida , pero no la parte glob , por lo que debe deshabilitarse (set -o noglob).
  • Debe ser grep -xFe "$name" -A1 phonebook.txt o grep -xFA1 -- "$name" phonebook.txt o no ' funcionará correctamente si $name comienza con - o $POSIXLY_CORRECT está en el entorno.
  • En bash, ' es [[ $string = $pattern ]] o [[ $string = "$otherstring" ]]. O IOW, debe citar las expansiones de palabras en el lado derecho del operador = dentro de [[...]] si no lo hace ' No quiero que se tome como un patrón.

Respuesta

index=0 while read line; do myArray[index]="$line" done < inputfile 

Las versiones más recientes de bash admiten matrices asociativas. Eso lo haría más fácil:

declare -A myArray while read name; do read number myArray[name]="$number" done < inputfile echo ${myArray[name]} 

Comentarios

  • y cómo devolvería el elemento de myArray [nombre + 1]?
  • En el ejemplo indexado, usted ya tenía la solución, por lo que no ' t la copié.
  • ¿Puedo estar equivocado, pero el uso de dicha tubería no haría que myArray " invisible " fuera del bucle ???
  • @FredericYesidPe ñ aS á nchez Ni la pregunta ni mi respuesta contienen una canalización, por lo que no ' t sé de lo que estás hablando.
  • " while read name; " me parece un pipeline, de todos modos, encontré que " declare -a array " soluciona problemas que tenía antes, ¡gracias! +1

Responder

En una pregunta titulada « BASH leyendo un archivo txt y almacenándolo en una matriz «Siento que readarray merece una mención. Un ejemplo de este método que utilizo para leer archivos de prueba en una matriz sería:

readarray -t arrayIPblacklist < /etc/postfix/IP-black-list.txt 

Lo anterior carga un archivo de direcciones IP, separadas por líneas nuevas, en una matriz llamada « arrayIPblacklist «. Trabajaría en su archivo de directorio telefónico. readarray se introdujo en bash 4, por lo que este método no funcionará en hosts más antiguos que ejecuten versiones de bash anteriores.

El -t elimina los delimitadores de nueva línea de cada elemento, ya que la mayoría de las veces no desea que se incluyan.

$ seq 3 | bash -c "readarray a; printf "<%q>\n" "${a[@]}"" <$"1\n"> <$"2\n"> <$"3\n"> $ seq 3 | bash -c "readarray -t a; printf "<%q>\n" "${a[@]}"" <1> <2> <3> 

Comentarios

  • Tenga en cuenta que la respuesta aceptada ya mencionó mapfile, que es otro nombre (aunque más confuso) para readarray incorporado.
  • Mi bad- no ' ver eso. ¡Gracias @St é phaneChazelas!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *