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
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
ogrep -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) parareadarray
incorporado. - Mi bad- no ' ver eso. ¡Gracias @St é phaneChazelas!
grep -P -o "(?<=$NOME\t).+"