Đầu ra khác nhau từ hai chương trình không có tệp tạm thời


Câu trả lời:


211

Sử dụng <(command)để chuyển đầu ra của một lệnh sang chương trình khác như thể đó là tên tệp. Bash chuyển đầu ra của chương trình sang một ống và truyền tên tệp như /dev/fd/63cho lệnh bên ngoài.

diff <(./a) <(./b)

Tương tự như vậy bạn có thể sử dụng >(command)nếu bạn muốn chuyển một cái gì đó thành một lệnh.

Điều này được gọi là "Thay thế quy trình" trong trang người đàn ông của Bash.


1
Một nhược điểm cần lưu ý là nếu ./a hoặc ./b không thành công, người gọi sẽ không phát hiện ra điều đó.
Alexander Pogrebnyak

5
OP đã gắn thẻ bash câu hỏi, nhưng đối với bản ghi, điều này không hoạt động trong bất kỳ shell nào khác. Đây là một phần mở rộng bash cho tiêu chuẩn tiện ích Posix.
DigitalRoss

5
Tôi đã thử giải pháp này với một chương trình Java và gặp lỗi này : -bash: syntax error near unexpected token ('. Tôi đã thử lại mà không có dấu ngoặc đơn và có -bash: java: No such file or directory. Nó không hoạt động nếu lệnh có tham số?
styfle

1
@DigitalRoss - Giải pháp có thể được mở rộng sang các shell khác bằng cách sử dụng bí danh. Trong tcsh, sự xấu xí sau đây hoạt động : alias diffcmd bash -c \'diff \<\(sh -c \!:1\) \<\( sh -c \!:2 \)\'. (Sau đó, ví dụ: diffcmd "ls" "ls -a").
Paul Lynch

Đối với bất kỳ ai lang thang ngoài Google, điều này cũng hoạt động theo zsh. (Ngoài ra, nếu bạn cần cung cấp đầu vào vào thứ gì đó gọi fseek, zsh cung cấp =(./a)có thể được sử dụng giống hệt <(./a)nhưng sử dụng tệp tạm thời trong mui xe, zsh sẽ xóa cho bạn.)
ssokolow

26

Thêm vào cả hai câu trả lời, nếu bạn muốn xem so sánh cạnh nhau, hãy sử dụng vimdiff:

vimdiff <(./a) <(./b)

Một cái gì đó như thế này:

nhập mô tả hình ảnh ở đây


vimdifftạo ra các quan điểm so sánh khác biệt đẹp, thông minh và tương tác. Nó dường như đi kèm với vimgói trên hầu hết các hệ thống.
Tim Visée

vimdiffcũng cho thấy không chỉ dòng khác nhau mà cả đoạn văn bản cụ thể khác nhau.
Anton Tarasenko


15

Đối với bất kỳ ai tò mò, đây là cách bạn thực hiện thay thế quy trình bằng cách sử dụng Vỏ cá :

Bash:

diff <(./a) <(./b)

Cá:

diff (./a | psub) (./b | psub)

Thật không may, việc thực hiện trên cá hiện đang thiếu ; cá sẽ treo hoặc sử dụng một tập tin tạm thời trên đĩa. Bạn cũng không thể sử dụng psub cho đầu ra từ lệnh của bạn.


Điều này hiện không hoạt động chính xác trong cá. Nếu đầu ra của các chương trình lớn hơn một BUFSIZ, lệnh sẽ bị treo. (hoặc cá thực sự sẽ chỉ sử dụng một tệp tạm thời trên đĩa)
Evan Benn

7

Thêm một chút nữa vào các câu trả lời đã tốt (đã giúp tôi!):

Lệnh dockerxuất ra trợ giúp của nó STD_ERR(tức là mô tả tệp 2)

Tôi muốn xem nếu docker attachdocker attach --helpđưa ra cùng một đầu ra

$ docker attach

$ docker attach --help

Vừa gõ hai lệnh đó, tôi đã làm như sau:

$ diff <(!-2 2>&1) <(!! 2>&1)

!! giống như! -1 có nghĩa là chạy lệnh 1 trước lệnh này - lệnh cuối cùng

! -2 có nghĩa là chạy lệnh hai trước lệnh này

2> & 1 có nghĩa là gửi đầu ra file_descriptor 2 (STD_ERR) đến cùng một nơi với đầu ra file_descriptor 1 (STD_OUT)

Hy vọng điều này đã được sử dụng.


0

Đối với zsh, sử dụng =(command)tự động tạo một tệp tạm thời và thay thế =(command)bằng đường dẫn của chính tệp đó. Với Thay thế quy trình thông thường, $(command)được thay thế bằng đầu ra của lệnh.

Tính năng zsh này rất hữu ích và có thể được sử dụng như vậy để so sánh đầu ra của hai lệnh bằng công cụ diff, ví dụ Beyond Beyond:

bcomp  =(ulimit -Sa | sort) =(ulimit -Ha | sort)

Đối với Beyond So sánh, lưu ý rằng bạn phải sử dụng bcompcho mục đích trên (thay vì bcompare) kể từ khi bcompkhởi chạy so sánh và chờ đợi nó hoàn thành. Nếu bạn sử dụng bcompare, nó sẽ khởi chạy so sánh và thoát ngay lập tức do các tệp tạm thời được tạo để lưu trữ đầu ra của các lệnh biến mất.

Đọc thêm tại đây: http://zsh.sourceforge.net/Intro/intro_7.html

Cũng lưu ý điều này:

Lưu ý rằng shell tạo một tệp tạm thời và xóa nó khi lệnh kết thúc.

và sau đây là sự khác biệt giữa $(...)=(...):

Nếu bạn đọc trang man của zsh, bạn có thể nhận thấy rằng <(...) là một hình thức thay thế quy trình khác tương tự như = (...). Có một sự khác biệt quan trọng giữa hai. Trong trường hợp <(...), shell tạo ra một ống có tên (FIFO) thay vì một tệp. Điều này là tốt hơn, vì nó không lấp đầy hệ thống tập tin; nhưng nó không hoạt động trong mọi trường hợp. Trên thực tế, nếu chúng ta đã thay thế = (...) bằng <(...) trong các ví dụ ở trên, tất cả chúng sẽ ngừng hoạt động ngoại trừ fgrep -f <(...). Bạn không thể chỉnh sửa đường ống hoặc mở nó dưới dạng thư mục thư; fgrep, tuy nhiên, không có vấn đề với việc đọc danh sách các từ từ một đường ống. Bạn có thể tự hỏi tại sao thanh diff <(foo) không hoạt động, vì foo | công trình khác biệt; điều này là do diff tạo một tệp tạm thời nếu nó thông báo rằng một trong các đối số của nó là - và sau đó sao chép đầu vào tiêu chuẩn của nó vào tệp tạm thời.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.