Làm thế nào để hoàn tác các thay đổi trong lịch sử lệnh?


12

Trong các hệ thống UNIX, bạn có thể nhấn các mũi tên trên và dưới để điều hướng qua các lệnh trước đó. Điều này là vô cùng tiện dụng.

Đôi khi, tôi đi lên và tìm thấy một lệnh mà tôi muốn sử dụng lại, nhưng với một số biến thể. Nếu tôi thực hiện các thay đổi như vậy, thì tôi không có cách nào để lấy lại lệnh gốc, trừ khi tôi kiểm tra nó history.

Có cách nào để "hoàn tác" các thay đổi đối với lệnh trong lịch sử được truy cập thông qua các khóa không?

Cách giải quyết hiện tại của tôi là trả trước một #lệnh. Bằng cách này, lệnh hiện tại được thực hiện như một bình luận, vì vậy không có gì xảy ra. Sau đó, tôi có thể duyệt lại thông qua các lệnh bằng các phím. Vấn đề là lệnh tôi đang sử dụng có thể rất xa trong danh sách, vì vậy việc tăng trở lại hai trăm lần là một chút. Control + R cũng không phải là một giải pháp, vì tôi có thể không nhớ chính xác những gì tôi đang tìm kiếm.

Thí dụ

Tôi đã gõ "50 lệnh trước" sau đây:

ls -l /etc/httpd/conf/

Bây giờ tôi đã đi đến dòng đó và thay đổi nó thành

ls -l /etc/init.d/

nhưng không nhấn enter. Bây giờ, tôi muốn ls -l /etc/httpd/conf/trở lại.

Môi trường của tôi

$ echo $SHELL
/bin/bash
$ echo $TERM
xterm

Lịch sử lệnh được thay đổi có khả năng là một tính năng (mis-) của trình bao bạn đang sử dụng. Trong kshVí dụ, bạn có thể chỉnh sửa các mục lịch sử và invoke họ mà không xóa các "phiên bản trước" của sự xâm nhập; bạn có tất cả các lệnh được gọi có sẵn.
Janis

Với "nó thay đổi" Ý tôi là: đưa ra một lệnh trước đó mà tôi đã thay đổi sau khi tiếp cận nó bằng mũi tên, nếu tôi đi lên và xuống bằng mũi tên, lệnh cũ sẽ không hiển thị theo cách đó, nhưng cách tôi đã sửa đổi nó Tất nhiên, nếu tôi gõ "enter" thực hiện một lệnh, lệnh cũ đó sẽ như ban đầu; nhưng đây chính xác là những gì tôi đang cố gắng tránh và tìm cách "thiết lập lại" lệnh về giá trị ban đầu.
fedorqui

1
Cũng trong trường hợp này, kshdường như hành vi của nó khác ở đây. Và các tùy chọn chỉnh sửa lịch sử của bạn cũng phụ thuộc vào chế độ chỉnh sửa được chọn. Trong ksh's vi-mode, ví dụ, các mục nhập cũ không ghi đè, và tôi cũng có thể phát hành một lệnh lùi lại, như trong vi, với 'u'.
Janis

Uhms, điều này nghe có vẻ rất hứa hẹn. Tôi hiện đang làm việc tại Bash và hiện không xem xét để thay đổi ksh, nhưng thật tốt khi biết điều đó tồn tại ở đó.
fedorqui

Tôi muốn biết nơi bash lưu trữ lịch sử lệnh gần đây trước khi ghi vào tệp lịch sử khi trình bao được đóng. Nó có thể giúp xác định nếu điều này là có thể. Có ai không Tôi nghĩ rằng nó có thể là một trong những biến vỏ, nhưng không có thời gian để xem hướng dẫn sử dụng ngay bây giờ.
iyrin

Câu trả lời:


10

Miễn là bạn đã chỉnh sửa mục nhập lịch sử nhưng chưa được nhấn Enter, để quay lại mục nhập ban đầu, liên tục nhấn Ctrl+ _- undolệnh - cho đến khi nó không thực hiện bất kỳ thay đổi nào nữa. Bạn đang trở lại mục nhập ban đầu.


5

Hoàn nguyên về lệnh ban đầu khi bạn đã thực hiện nhiều thay đổi cho dòng:

revert-line (M-r) 
    Undo all changes made to this line. This is like 
executing the undo command enough times to get back to the beginning.

Mlà khóa meta, altrdành cho tôi.


Vô cớ, nhưng thông tin hữu ích

Khi bạn đã thực thi một lệnh như OP đã thực hiện trước đó (nó xảy ra), sẽ không có gì để "hoàn tác" vì các lệnh được thư viện GNU Readline xử lý và ghi nhớ và không được ghi cho$HISTFILE đến khi thoát khỏi trình bao. Lý do tôi đề cập đến điều này là do bạn không thể chỉ grep$HISTFILEnhư người ta có thể mong đợi và nó có thể không lý tưởng để thoát khỏi vỏ.

Vì vậy, đây là một vài tùy chọn để giúp bạn không phải cuộn qua tất cả các lệnh đọc trước đó.

Nếu bạn nhớ một số lệnh , nhấn ctrl+ rvà nhập những gì bạn nhớ để tìm kiếm thông qua các lệnh trước đó có chứa chuỗi đó. Nhấn ctrl+ rlần nữa sẽ hiển thị gần đây nhất, tìm kiếm ngược.

Ví dụ: nhập ls -lthen ctrl+ rnhiều lần để tìm lệnh trước đó bạn tìm kiếm. Nếu bạn cuộn qua nó, ctrl+ ssẽ tìm kiếm chuyển tiếp từ vị trí hiện tại.

Lệnh fcbash dựng sẵn rất hữu ích để liệt kê các số chỉ mục cùng với các lệnh đọc trước đó.

fc -l -100 sẽ liệt kê 100 lệnh trước đó trong readline.

Ngoài ra, nếu OP biết anh ta đang tìm kiếm một ls -llệnh trước đó , anh ta có thể chuyển đầu ra thành grep:fc -l -100 | grep 'ls -l'

Điều này sẽ xuất ra một danh sách các ls -llệnh trước có trước một số chỉ mục. Đầu ra trông như thế này:
2065 ls -l

Bây giờ bạn có thể sử dụng trình chỉ định sự kiện !ntrong đó nlà số chỉ mục. Trong ví dụ này, thực thi !2065sẽ mở rộng đến ls -l.


Mặc dù thực tế nó không giúp ích gì, nhưng bất kỳ ai đang tìm cách lưu lại lịch sử lệnh gần đây khi sửa đổi các lệnh trước đó sẽ thấy HISTORY EXPANSIONphần của man bash. Dưới đây là một số phương pháp thay thế để sửa đổi các lệnh cũ mà không ghi đè lên lịch sử.

Phần Event Designatorsnày cho thấy cách bạn có thể dễ dàng chỉnh sửa chuỗi từ lệnh được sử dụng gần đây nhất.

^string1^string2^
              Quick  substitution.  Repeat the previous command, replacing string1 with string2.  Equivalent to
              ``!!:s/string1/string2/'' (see Modifiers below).

Thí dụ:

$ echo foo
foo 
$ ^foo^bar
echo bar
bar

Các lệnh gần đây nhất sẽ hiển thị:

echo foo
echo bar

Ví dụ trên cũng giải thích cách sử dụng sedđể thay thế một chuỗi trong trình chỉ định sự kiện.

!-n    Refer to the current command minus n.

Vì vậy, nếu có 3 lệnh trong lịch sử echo foothì bạn sẽ sử dụng:
!-3:s/foo/bar

Lưu ý rằng các trình chỉ định sự kiện sẽ xuất hiện trong lịch sử của bạn khi lệnh được thực thi, trong trường hợp này echo bar. Nó sẽ không xuất hiện trong lịch sử như !-3:s/foo/bar.

Chỉ cần ném nó ra khỏi đó vì nó có vẻ liên quan chặt chẽ, ngay cả khi đó là một giải pháp "không nên làm" hơn là giải pháp "hoàn tác" mà OP đang tìm kiếm.


Điều này là tốt đẹp, cảm ơn rất nhiều cho các thông tin chi tiết. Tôi chấp nhận câu trả lời của Gilles vì ​​nó thực hiện chính xác những gì tôi đang tìm kiếm, trong khi ở đây bạn cho rằng tôi biết nhiều điều về lệnh tôi muốn làm lại, điều này không phải lúc nào cũng đúng.
fedorqui

Vâng tôi đồng ý. Sẽ thật tuyệt nếu tính năng hoàn tác đó được mở rộng cho các lệnh trước đây tôi đã nhập lệnh.
iyrin
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.