2012-03-23 11 views
34

Tengo problemas con esta tarea simple:Uso tubería de comandos como argumento para diff

cat file | grep -E ^[0-9]+$ > file_grep 
diff file file_grep 

El problema es que yo quiero hacer esto sin file_grep

que he intentado:

diff file `cat file | grep -E ^[0-9]+$` 

y

diff file "`cat file | grep -E ^[0-9]+$`" 

y algunas otras combinaciones :-) pero no puedo hacer que funcione. Siempre obtengo un error cuando el diff obtiene un argumento adicional que es contenido del archivo filtrado por grep.

Algo parecido siempre ha trabajado para mí, cuando quería echo salidas de comando desde dentro de un script como el siguiente (utilizando comillas invertidas escapa):

echo `ls` 

Gracias

Respuesta

38

Si está utilizando bash:

diff file <(grep -E '^[0-9]+$') file 

La secuencia <(COMMAND) expande al nombre de un pseudo-archivo (como /dev/fd/63) desde donde se puede leer la salida del comando.

Pero para este caso en particular, la solución de ruakh es más simple. Aprovecha el hecho de que - como argumento en diff hace que lea su entrada estándar. La sintaxis <(COMMAND) se vuelve más útil cuando ambos argumentos a diff se emiten comandos, tales como:

diff <(this_command) <(that_command) 
35

El enfoque más simple es:

grep -E '^[0-9]+$' file | diff file - 

El guión - como el nombre del archivo es una notación específica que dice diff "use la entrada estándar" ; está documentado en la página de manual diff. (La mayoría de las utilidades comunes admiten la misma notación.)

La razón por la que los retrocesos no funcionan es porque capturan la salida de un comando y lo pasan como argumento. Por ejemplo, esto:

cat `echo file` 

es equivalente a esto:

cat file 

y esto:

diff file "`cat file | grep -E ^[0-9]+$`" 

es equivalente a algo como esto:

diff file "123 
234 
456" 

Eso es , en realidad trata de pasar 123234345 (más líneas nuevas) como nombre de archivo, en lugar de como contenidos de un archivo. Técnicamente, se podría lograr esto último mediante la característica de Bash "sustitución de proceso" que en realidad crea una especie de archivo temporal:

diff file <(cat file | grep -E '^[0-9]+$') 

pero en su caso no se necesita, debido al apoyo diff 's para -.

+0

Gracias por su ayuda :-) – rluks

+0

@ Pan.student: ¡De nada! – ruakh

+0

¿Puedo poner todo el comando en prueba de esta manera? 'if [-z grep -E '^ [0-9] + $' archivo | archivo diff -]; entonces echo "coincide con" fi' – rluks

3

En bash, la sintaxis es

diff file <(cat file | grep -E ^[0-9]+$) 
4

Try sustitución de proceso:

$ diff file <(grep -E "^[0-9]+$" file) 

De la página de manual de bash:

Sustitución de proceso

La sustitución de procesos se admite en sistemas que admiten canalizaciones con nombre (FIFO) o el método/dev/fd de nombrando archivos abiertos. Toma la forma de < (lista) o> (lista). La lista de procesos se ejecuta con su entrada o salida conectada a un FIFO o algún archivo en/dev/fd. El nombre de este archivo se pasa como argumento al el comando actual como resultado de la expansión. Si se usa el formulario> (lista), escribir en el archivo proporcionará entrada para la lista. Si se utiliza el formulario < (lista), el archivo pasado como argumento debe leerse para obtener el resultado de la lista.

+0

Funciona también, gracias – rluks

7
grep -E '^[0-9]+$' file | diff - file 

donde - significa "leer de la entrada estándar".

Cuestiones relacionadas