Использовать команду команд в качестве аргумента для diff
У меня возникают проблемы с этой простой задачей:
cat file | grep -E ^[0-9]+$ > file_grep
diff file file_grep
Проблема в том, что я хочу сделать это без file_grep
Я пробовал:
diff file `cat file | grep -E ^[0-9]+$`
и
diff file "`cat file | grep -E ^[0-9]+$`"
и несколько других комбинаций:-), но я не могу заставить его работать.
Я всегда получаю сообщение об ошибке, когда diff
получает дополнительный аргумент, который является содержимым файла, отфильтрованного grep
.
Что-то подобное всегда срабатывало для меня, когда я хотел echo
выводить команды из script как это (используя escape-обратные экраны):
echo `ls`
Спасибо
Ответы
Ответ 1
Если вы используете bash:
diff file <(grep -E '^[0-9]+$') file
Последовательность <(COMMAND)
расширяется до имени псевдофайла (например, /dev/fd/63
), из которого вы можете прочитать вывод команды.
Но для этого конкретного случая решение руаха проще. Он использует тот факт, что -
как аргумент diff
заставляет его читать стандартный ввод. Синтаксис <(COMMAND)
становится более полезным, когда оба аргумента diff
являются выходными данными команды, такими как:
diff <(this_command) <(that_command)
Ответ 2
Самый простой способ:
grep -E '^[0-9]+$' file | diff file -
Дефис -
в качестве имени файла представляет собой конкретную нотацию, которая сообщает diff
"использовать стандартный ввод"; он задокументирован в man-странице diff
. (Большинство общих утилит поддерживают одну и ту же нотацию.)
Причина, по которой backticks не работает, заключается в том, что они захватывают вывод команды и передают ее в качестве аргумента. Например, это:
cat `echo file`
эквивалентно этому:
cat file
и это:
diff file "`cat file | grep -E ^[0-9]+$`"
эквивалентно примерно так:
diff file "123
234
456"
То есть, он фактически пытается передать 123234345
(плюс новые строки) как имя файла, а не как содержимое файла. Технически вы могли бы достичь последнего, используя функцию Bash "замещение процесса", которая фактически создает своего рода временный файл:
diff file <(cat file | grep -E '^[0-9]+$')
но в вашем случае это не нужно, из-за diff
поддержки -
.
Ответ 3
grep -E '^[0-9]+$' file | diff - file
где -
означает "читать со стандартного ввода".
Ответ 4
Попробуйте заменить процесс:
$ diff file <(grep -E "^[0-9]+$" file)
Из bash manpage:
Замена процесса
Подстановка процесса поддерживается в системах, которые поддерживают именованные каналы (FIFO) или метод /dev/fd Именование открытых файлов. Он принимает форму < (list) или > (list). Список процессов запускается со своим вводом или вывода, подключенного к FIFO или некоторому файлу в /dev/fd. Имя этого файла передается как аргумент текущая команда в результате расширения. Если используется формa > (список), запись в файл предоставит вход для списка. Если используется форма < (list), файл, переданный как аргумент, должен быть прочитан для получения вывода списка.
Ответ 5
В bash синтаксис
diff file <(cat file | grep -E ^[0-9]+$)