I am having trouble with this simple task:
cat file | grep -E ^[0-9]+$ > file_grep
diff file file_grep
Problem is, I want to do this without
In bash, the syntax is
diff file <(cat file | grep -E ^[0-9]+$)
grep -E '^[0-9]+$' file | diff - file
where -
means "read from standard input".
The simplest approach is:
grep -E '^[0-9]+$' file | diff file -
The hyphen -
as the filename is a specific notation that tells diff
"use standard input"; it's documented in the diff
man-page. (Most of the common utilities support the same notation.)
The reason that backticks don't work is that they capture the output of a command and pass it as an argument. For example, this:
cat `echo file`
is equivalent to this:
cat file
and this:
diff file "`cat file | grep -E ^[0-9]+$`"
is equivalent to something like this:
diff file "123
234
456"
That is, it actually tries to pass 123234345
(plus newlines) as a filename, rather than as the contents of a file. Technically, you could achieve the latter by using Bash's "process substitution" feature that actually creates a sort of temporary file:
diff file <(cat file | grep -E '^[0-9]+$')
but in your case it's not needed, because of diff
's support for -
.
If you're using bash:
diff file <(grep -E '^[0-9]+$' file)
The <(COMMAND)
sequence expands to the name of a pseudo-file (such as /dev/fd/63
) from which you can read the output of the command.
But for this particular case, ruakh's solution is simpler. It takes advantage of the fact that -
as an argument to diff
causes it to read its standard input. The <(COMMAND)
syntax becomes more useful when both arguments to diff
are command output, such as:
diff <(this_command) <(that_command)
Try process substitution:
$ diff file <(grep -E "^[0-9]+$" file)
From the bash manpage:
Process Substitution
Process substitution is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files. It takes the form of <(list) or >(list). The process list is run with its input or output connected to a FIFO or some file in /dev/fd. The name of this file is passed as an argument to the current command as the result of the expansion. If the >(list) form is used, writing to the file will provide input for list. If the <(list) form is used, the file passed as an argument should be read to obtain the output of list.