2011-08-19 15 views
19

Me gustaría usar las líneas provenientes de 'wc' como variables. Por ejemplo:resultados de wc como variables

echo 'foo bar' > file.txt 
echo 'blah blah blah' >> file.txt 
wc file.txt 

2 5 23 file.txt 

me gustaría tener algo como $lines, $words y $characters asociado a los valores 2, 5 y 23. ¿Cómo puedo hacer eso en bash?

Respuesta

7

Hay otras soluciones sino una simple que lo general el uso es para poner la salida del wc en un archivo temporal, y luego leer desde allí:

wc file.txt > xxx 
read lines words characters filename < xxx 
echo "lines=$lines words=$words characters=$characters filename=$filename" 
lines=2 words=5 characters=23 filename=file.txt 

La ventaja de este método es que no necesita crear varios procesos awk, uno para cada variable. La desventaja es que necesita un archivo temporal, que debe eliminar después.

Tenga cuidado: esto no funciona:

wc file.txt | read lines words characters filename 

El problema es que la tubería para read crea otro proceso, y las variables se actualizan allí, por lo que no son accesibles en la cáscara de llamada.

Editar: la adición de la solución por arnaud576875:

read lines words chars filename <<< $(wc x) 

obras sin escribir en un archivo (y no tienen un problema de la tubería). Es bash específico.

Desde el manual de bash:

Here Strings 

    A variant of here documents, the format is: 

      <<<word 

    The word is expanded and supplied to the command on its standard input. 

La clave es la "palabra se expande" bits.

+0

Mejor que el mío, pero no necesita el archivo 'xxx' o el nombre del archivo:' wc

+0

@Adrian: vea mi comentario anterior: la tubería crea variables en otro proceso, por lo que no están disponibles en el intérprete de comandos. – dangonfast

+5

'leer líneas palabras caracteres <<< $ (wc x)' funciona sin escribir en un archivo (y no tiene problema con la tubería) – arnaud576875

3
lines=`wc file.txt | awk '{print $1}'` 
words=`wc file.txt | awk '{print $2}'` 
... 

También puede guardar el resultado wc lugar primero .. y luego analizarlo .. si eres exigente con el rendimiento :)

0

Puede asignar la salida a una variable mediante la apertura de una concha substitución:

$ x=$(wc some-file) 
$ echo $x 
1 6 60 some-file 

Ahora, con el fin de obtener las variables independientes, la opción más sencilla es utilizar awk:

$ x=$(wc some-file | awk '{print $1}') 
$ echo $x 
1 
30

En bash pura: (sin awk)

a=($(wc file.txt)) 
lines=${a[0]} 
words=${a[1]} 
chars=${a[2]} 

Esto funciona mediante el uso de matrices de bash. a=(1 2 3) crea una matriz con los elementos 1, 2 y 3. A continuación, podemos acceder a elementos separados con la sintaxis ${a[indice]}.

alternativa: (basado en la solución gonvaled)

read lines words chars <<< $(wc x) 

O en sh:

a=$(wc file.txt) 
lines=$(echo $a|cut -d' ' -f1) 
words=$(echo $a|cut -d' ' -f2) 
chars=$(echo $a|cut -d' ' -f3) 
+0

¿Puedes explicar por qué funciona? En particular, ¿qué hacen los paréntesis adicionales alrededor de la primera línea? Sin ellos, ya no funciona, por lo que parecen ser bastante importantes. –

+0

En bash, el '(...)' externo crea una matriz que las últimas líneas indexan. De lo contrario, el resultado es solo una cadena única de tres números –

+0

En este caso, los paréntesis son parte de la sintaxis de sustitución del comando $ (_ command_); es equivalente a \ 'comando \', pero la notación de paréntesis simplifica la anidación. El _command_ se ejecuta en una subshell, y el texto de la sustitución del comando se reemplaza por el resultado de _command_, casi como si lo hubiera tipeado. –

0
declare -a result 
result=($(wc < file.txt)) 
lines=${result[0]} 
words=${result[1]} 
characters=${result[2]} 
echo "Lines: $lines, Words: $words, Characters: $characters" 
4

sólo para añadir otra variante -

set -- `wc file.txt` 
chars=$1 
words=$2 
lines=$3 

Esto, obviamente, clobbers $* y variables relacionadas. A diferencia de algunas de las otras soluciones aquí, es portátil para otras conchas de Bourne.

Cuestiones relacionadas