Làm cách nào để sử dụng lại đầu ra cuối cùng từ dòng lệnh?


43

Tôi muốn biết cách sử dụng lại đầu ra cuối cùng từ bảng điều khiển, nghĩa là:

pv-3:method Xavier$ python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
/Library/Python/2.6/site-packages
pv-3:method Xavier$ cd **LASTOUTPUT**

7
Bạn không thể; có một số giải thích nền ở đây . Đặt cược tốt nhất của bạn là chạy lại lệnh, như đã thấy trong hai câu trả lời được đăng cho đến nay.
Gilles 'SO- ngừng trở nên xấu xa'

Bạn không thể chụp đầu ra được gửi trực tiếp đến một thiết bị như /dev/tty, nhưng có thể chụp bất cứ thứ gì được gửi đến stdouthoặc stderr, có thể là đủ.
Mikel

@Gilles - tất nhiên trừ khi bạn sử dụng câu trả lời của @ mattdm!
simon

@Gilles: nhưng có thể có một lớp vỏ được tạo bởi ai đó sẽ nắm bắt (và chuyển qua) các đầu ra của các lệnh và làm cho các đầu ra bị bắt có sẵn để người dùng tham khảo từ các lệnh tiếp theo của mình. Có lẽ, thậm chí còn có một số vỏ hiện tại, không phổ biến cho phép điều này với ít nhiều biến chứng ...
imz - Ivan Zakharyaschev

Câu trả lời:


39

Giả sử bash:

% python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
/usr/lib/python2.7/site-packages
% cd $(!!)
cd $(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")
% pwd
/usr/lib/python2.7/site-packages

1
Cảm ơn! Không quá dễ để gõ nhưng nó sẽ phù hợp với chuột.
phương pháp của

2
Bạn cũng có thể sử dụng backticks (mà tôi không thể tìm ra cách làm cho giao diện này không bị thay thế) thay vì $ (), nhưng tôi thấy rằng thật khó chịu khi tôi nhấn backtick-shift-1-shift-1-backtick và tôi đang cố gắng tập thói quen sử dụng $ () khi có thể vì mục đích dễ đọc.
jsbillings

@jsbillings xem câu trả lời của tôi dưới đây. Tôi đã gõ \ `để hiển thị` trong câu trả lời. Và để hiển thị '\', như loại thông thường '\'.
yasouser

3
+1 Tôi đã tự hỏi làm thế nào để làm tổ `backtick-commands`! cd $(dirname $(which python))tôi đến đây!
Ed Brannin

21
Chỉ cần một lưu ý, hãy nhớ rằng đây là chạy lại lệnh. Nếu lệnh của bạn có tác dụng phụ, điều này có thể không hiệu quả với bạn.
Rich Homolka

13

Chưa được đề cập, sử dụng một biến:

dir=$( python -c ... )
cd "$dir"

3
Chính xác. Bởi vì nó là một cái vỏ, mọi người thường quên đi các tính năng ngôn ngữ mà Bash cung cấp, chẳng hạn như các vòng lặp và gán.
Evan

chỉ có thể nóicd $dir
tạm

3
@Aerovistae, có dấu ngoặc kép được yêu cầu nếu bạn không biết trong đó giá trị xuất phát từ:
glenn jackman

@glenn, (Tôi biết đây có thể là một câu hỏi hoàn toàn khác, nhưng nếu câu trả lời ngắn :) bạn có thể giải thích thêm / cung cấp một ví dụ về việc không sử dụng dấu ngoặc kép sẽ phá vỡ mọi thứ không?
alexey

2
Lời giải thích kinh điển là unix.stackexchange.com/questions/171346/...
glenn Jackman

8

Tất cả các giải pháp khác liên quan đến việc sửa đổi quy trình công việc của bạn hoặc chạy lệnh hai lần, điều này có thể không phù hợp nếu mất nhiều thời gian để chạy hoặc không thể lặp lại (ví dụ: xóa một tệp - chạy lại nó sẽ tạo ra kết quả khác).

Vì vậy, đây là một ý tưởng phức tạp hơn nếu bạn cần nó:

.bashrc

exec > >(tee -a ~/$$.out)

PROMPT_COMMAND='LASTLINE=$(tail -n 1 ~/$$.out)'

trap 'rm ~/$$.out' EXIT

nhắc nhở

$ python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
/usr/lib/python2.6/dist-packages
$ cd $LASTLINE
$ pwd
/usr/lib/python2.6/dist-packages

Điều này có một số vấn đề, vì vậy nó chỉ có ý nghĩa như một điểm khởi đầu. Ví dụ: tệp đầu ra ( ~/<pid>.out) có thể phát triển rất lớn và lấp đầy đĩa của bạn. Ngoài ra, toàn bộ vỏ của bạn có thể ngừng hoạt động nếu teechết.

Nó có thể được sửa đổi để chỉ thu được đầu ra từ lệnh trước đó bằng cách sử dụng preexecprecmdhook trong zsh, hoặc mô phỏng chúng trong bash, nhưng điều đó phức tạp hơn để mô tả ở đây.


6
Ý tưởng cơ bản là tốt, nhưng việc thực hiện thì không. Đầu ra tiêu chuẩn trong phiên shell không phải là một thiết bị đầu cuối mà là một đường ống, điều này sẽ khiến một số chương trình hoạt động khác đi. Sẽ không có bất kỳ sự đồng bộ nào giữa ghi vào thiết bị xuất chuẩn và ghi vào thiết bị xuất chuẩn hoặc trực tiếp đến tty, vì vậy, ví dụ bạn có thể thấy đầu ra lệnh được hiển thị sau dấu nhắc tiếp theo. Bạn cũng không được bảo vệ teekhỏi các tín hiệu (thử nhấn Ctrl+Cvà chạy thêm một vài lệnh). Sử dụng các scripttiện ích không có những vấn đề này.
Gilles 'SO- ngừng trở nên xấu xa'

Tốt để biết! Tôi vẫn đang làm việc với những điều cơ bản về dòng lệnh của mình vì vậy đây có thể là một việc quá mức đối với tôi, cộng với tôi muốn có thể sử dụng nó trên bất kỳ máy tính nào, nhưng tôi sẽ nhớ nó nếu tôi đạt đến mức tốt.
phương pháp của

8

Một dự thảo làm việc cho một vỏ truyền thống:

ttyid=$(readlink /proc/$$/fd/1)
\___/   \______/ \___/ |  |  |
  |         |      |   |  |  \- 0: stdin 
  |         |      |   |  |     1: stdout <- our interest
  |         |      |   |  |     2: stderr
  |         |      |   |  \- fd is, maybe, filedescriptor
  |         |      |   |
  |         |      |   \- $$ is the PID of the current process (shell,
  |         |      |      in our case)
  |         |      |
  |         |      \- you know, much runtime stuff is here
  |         |
  |         \- readlink extracts the symbolic link of /proc/$$/fd/1
  |            lrwx------ 1 stefan stefan 64 2011-03-18 09:11
  |            /proc/22159/fd/1 -> /dev/pts/4
  |
  \- /dev/tty3 for real shell, /dev/pts/3 for xterm

Bây giờ chúng ta có thể cat màn hình vào một tập tin. Nhu cầu sudo.

id=${ttyid//\/dev\/tty}
sudo cat /dev/vcs$id > screen.dump

Apropose screendump: vì vậy chương trình được đặt tên không còn hiệu quả với tôi nữa. Có lẽ chỉ dành cho hạt nhân cũ. / dev / pts / N cũng không hiệu quả với tôi. Có thể bạn phải có một số MKDEV tùy chọn trong / dev - Tôi nhớ rất rõ về một số /dev/cuaN, nhưng tôi có thể sai.

Chúng tôi muốn chuyển đầu ra thay vì sử dụng screen.dump. Nhưng bằng cách nào đó nó không hoạt động - đôi khi nó chờ ENTER.

Việc chụp không phải là một tệp văn bản thông thường với các nguồn cấp dữ liệu, nhưng với - ví dụ - ký tự 80x50 trong một chuỗi.

Để chọn 2 dòng cuối cùng, 1 cho đầu ra của lệnh và một cho dòng nhắc nhở, tôi hoàn nguyên nó, chọn 160 ký tự, hoàn nguyên lại và chọn 80.

rev vcs4.dat | sed 's/\(.\{160\}\).*/\1/g' | rev | sed 's/\(.\{80\}\).*/\1/g'

Chỉ trong trường hợp bạn từng tự hỏi, tại sao có một revchương trình.

Phê bình:

  • Các lệnh đầu tiên được nhập, do đó di chuyển dòng ahed. Chà - chỉ là một bài tập số để chọn dòng thứ 3 hoặc thứ gì đó. Tôi làm việc chủ yếu ở một cửa sổ khác.
  • Không phải ai cũng có màn hình 80x50. Vâng, vâng, chúng tôi biết. Có $ COLUMNS và $ ROWS cho niềm vui của bạn.
  • Đầu ra không phải là tất cả ở phía dưới. Một vỏ tươi và trẻ có thể ở hàng trên. Vâng - đơn giản như vậy: Đánh giá cái gì đang chạy. Dấu nhắc nào được sử dụng. Thực hiện một số phát hiện nhanh chóng và tìm dòng cuối cùng với dấu nhắc shell. Dòng trước (hoặc 2. trước) nên chứa thư mục.

Sơ đồ đầu tiên được thực hiện với giải thích


+1, bắt tôi làmalias tee2tty='tee $(readlink /proc/$$/fd/1)'
Tobias Kienzler

7

Thử đi:

$ cd $(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")
$ pwd
/Library/Python/2.6/site-packages

6

Vì vậy, uh, đây là một câu trả lời:

Nếu bạn đang chạy dưới X, chọn đầu ra bạn muốn bằng chuột để sao chép nó, sau đó bấm giữa để dán nó.

Nếu bạn đang chạy trên bảng điều khiển văn bản, bạn có thể làm điều tương tự với gpm .


1
+1 - câu trả lời tốt! bạn có thể đạt được điều tương tự, ngay cả khi bạn không chạy X, bằng cách sử dụng màn hình GNU ( gnu.org/software/screen ).
simon

1
Có vẻ như quá rõ ràng đến nỗi tôi đã do dự để nói điều đó. Nhưng mọi người khác rất bận rộn để được thông minh. :)
mattdm

Đây là câu trả lời duy nhất ở đây cho phép OP sử dụng lại dòng cuối cùng - mọi thứ khác đòi hỏi phải chạy lại lệnh, có thể là bất cứ nơi nào giữa hoàn toàn không liên quan và thảm khốc :) Nhưng OP đã nói sử dụng lại .
simon

@simon: Thật ra, câu trả lời của tôi không. Glenn's cũng không.
Mikel

@Mikel: Đúng, nhưng họ yêu cầu bạn làm điều gì đó trước, hoặc chính xác ngay lần đầu tiên.
mattdm

1

(Thật không may là một câu trả lời hiệu quả, thật không may, nhưng vẫn có một điều gì đó gây tò mò. Ai đó quan tâm cũng có thể cố gắng hoàn thành việc thực hiện tính năng mà tôi sẽ nói với bạn.)

eshellbên trong Emacs, họ muốn có một tính năng như vậy nhưng nó không được triển khai theo cách hoàn chỉnh (tuy nhiên được phản ánh trong tài liệu ).

Ví dụ:

~ $ pwd
~
~ $ /bin/echo $$
~
~ $ /bin/pwd
/home/imz
~ $ /bin/echo $$

~ $ 

Bạn thấy đấy, chỉ có đầu ra của nội dung có thể được bắt vào $$biến.

Nhưng tốt, một số lập trình elisp (xem eshell-mark-outputtriển khai trong "esh-mode.el") và bạn có thể thực hiện một chức năng "đánh dấu" đầu ra cuối cùng và trả về nó như là kết quả của hàm; để bạn có thể sử dụng hàm đó trong lệnh eshell mà bạn đang yêu cầu - các hàm elisp có thể được sử dụng trong các lệnh eshell với cú pháp elisp thông thường, tức là trong ngoặc đơn, như sau:

~ $ /bin/echo (buffer-name)
*eshell*
~ $ /bin/echo (car '(a b c))
a
~ $ 

0

Nếu bạn nhận ra rằng bạn sẽ muốn sử dụng lại đầu ra trước khi nhấn Enter, bạn có thể lưu nó vào một biến: thêm tmp=$(vào đầu dòng và )ở cuối dòng. (Điều này loại bỏ bất kỳ dòng trống nào ở cuối đầu ra lệnh và trên thực tế sẽ loại bỏ bất kỳ dòng mới nào cuối cùng; điều này hiếm khi quan trọng.)

tmp=$(python -c )
echo "$tmp"
cd "$tmp"

Nếu shell của bạn là ksh hoặc zsh, đây là một chức năng hữu ích mà bạn có thể sử dụng để làm cho điều này tự động hơn. (Không có trợ giúp trong bash vì nó yêu cầu lệnh cuối cùng trong một đường ống được thực thi trong shell cha, đây chỉ là trường hợp trong ksh (không phải pdksh) và zsh.)

keep () {
  local line IFS=$'\n'
  kept=
  while read -r line; do
    printf '%s\n' "$line"
    kept=$kept$line$IFS
  done
}
alias keep=k

Sử dụng theo cách này:

python -c  |k
cd $kept

0
cd $(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" | tee $(readlink /proc/$$/fd/1))

(xây dựng câu trả lời của 4485 )

Đó là rất nhiều gõ, vì vậy hãy tạo một bí danh:

alias tee2tty='tee $(readlink /proc/$$/fd/1)'

Sau đó chỉ cần gọi cd $(python -c ... | tee2tty)

Điều này tất nhiên đòi hỏi bạn phải biết những gì bạn muốn làm với đầu ra nhưng có lợi thế là chỉ gọi lệnh một lần.



0

Có một giải pháp tốt hơn:

Chỉ cần in !!sau khi thực hiện lệnh và bạn sẽ nhận được đầu ra lặp đi lặp lại.

Ví dụ

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

Nguyên:

https://askubfox.com/questions/324423/how-to-access-the-last-return-value-in-bash


!!không lặp lại kết quả từ lệnh cuối cùng, nó chạy lại lệnh cuối cùng. Nếu jot -r 1 0 1000trả về một số ngẫu nhiên duy nhất trong khoảng từ 0 đến 1000, thì sau khi chạy lệnh đó một lần và nhận được 539, việc chạy !!nhiều khả năng sẽ đưa ra một số khác. !!cũng có thể là không mong muốn nếu lệnh trước đó mất thời gian đáng kể để chạy hoặc lặp lại một thao tác không nên lặp lại (như thay đổi tệp).
Caleb

1
bắt tốt Mặc dù có một cách dễ dàng hơn để chứng minh tôi sai: echo $ RANDOM; !!
Tebe

Ngọt ngào - không biết về điều đó! Cảm ơn.
Caleb
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.