2012-07-05 9 views
27

Duplicar posibles:
Looping through the content of a file in Bash?¿Cómo puedo iterar a través de líneas en un archivo externo con shell?

Tengo un archivo con una lista de nombres. Necesito recorrer todos los nombres en este archivo desde un archivo externo con un script de shell. ¿Cómo puedo hacer eso?

archivos Ejemplo:

scripts/nombres.txt

alison 
barb 
charlie 
david 

scripts/script.sh

NAMES="" #names from names.txt file 
for NAME in $NAMES; do 
    echo "$NAME" 
done 

¿Cómo puedo explotar el archivo nombres.txt en una matriz en una separada guión de shell?

+1

¿Qué tal un enlace a los Q & A original? – bearvarine

Respuesta

54

Una forma sería:

while read NAME 
do 
    echo "$NAME" 
done < names.txt 

EDIT: Tenga en cuenta que el bucle se ejecuta en un sub- shell, por lo que las variables modificadas serán locales, excepto si las declara con declare fuera del ciclo.

Dennis Williamson tiene razón. Lo siento, debo haber usado constructos de tuberías con demasiada frecuencia y me confundí.

+2

No, ya que nada está siendo canalizado en 'while', no hay subshell. La redirección a 'done' no crea una subcadena. –

+0

Por cierto, el problema (¿error?) Con las tuberías no ocurre con korn shell (pero sí con pdksh). – cdarke

5

Sé que los puristas odiarán este método, pero puede cat el archivo.

NAMES=`cat scripts/names.txt` #names from names.txt file 
for NAME in $NAMES; do 
    echo "$NAME" 
done 
+5

Esto tiene la ventaja de no invocar un subconjunto, pero considerará cualquier espacio en 'names.txt' como un delimitador. – smocking

+2

Los "puristas" también explicarán amablemente lo que está mal con esto. Hay múltiples problemas. Ver http://mywiki.wooledge.org/DontReadLinesWithFor – tripleee

6
cat names.txt|while read line; do 
    echo "$line"; 
done 
+4

'while read line; hacer ... done

13

que va a querer utilizar el 'leer' comando

while read name 
do 
    echo "$name" 
done < names.txt 

Tenga en cuenta que "$ name" es citado - si no es así, que se dividirá el uso de los caracteres en $IFS como delimitadores. Esto probablemente no se notará si solo hace eco de la variable, pero si su archivo contiene una lista de nombres de archivo que desea copiar, se desglosará por $IFS si la variable no está citada, que no es lo que usted querer o esperar

Si desea utilizar el enfoque de Mike Clark (cargar en una variable en lugar de utilizar leer), puede hacerlo sin el uso de cat:

NAMES="$(< scripts/names.txt)" #names from names.txt file 
for NAME in $NAMES; do 
    echo "$NAME" 
done 

El problema con esto es que se carga el conjunto archivo en $NAMES, cuando lo leyó de nuevo, puede obtener el archivo completo (si se cita) o el archivo desglosado por $IFS, si no se lo cita. Por defecto, esto le dará palabras individuales, no líneas individuales. Entonces, si el nombre "Mary Jane" aparecía en una línea, obtendría "Mary" y "Jane" como dos nombres separados. Usando read va a evitar esto ... aunque también se puede cambiar el valor de $IFS

2

Esto podría funcionar para usted:

cat <<\! >names.txt 
> alison 
> barb 
> charlie 
> david 
> ! 
OIFS=$IFS; IFS=$'\n'; NAMES=($(<names.txt)); IFS=$OIFS 
echo "${NAMES[@]}" 
alison barb charlie david 
echo "${NAMES[0]}" 
alison 
for NAME in "${NAMES[@]}";do echo $NAME;done 
alison 
barb 
charlie 
david 
Cuestiones relacionadas