cho biết nếu lệnh cuối cùng trống trong PROMPT_COMMAND


12

Trong bash, từ bên trong PROMPT_COMMAND, có cách nào để biết người dùng chỉ nhấn 'return' và không nhập lệnh không?

Câu trả lời:


7

Kiểm tra xem số lịch sử đã được tăng lên. Lời nhắc bị hủy hoặc lời nhắc mà người dùng vừa nhấn Entersẽ không tăng số lịch sử.

Số lịch sử có sẵn trong biến HISTCMD, nhưng số này không có sẵn PROMPT_COMMAND(vì thực tế bạn muốn có số lịch sử của lệnh trước đó; lệnh thực thi PROMPT_COMMANDchính nó không có số lịch sử). Bạn có thể lấy số từ đầu ra của fc.

prompt_command () {
  HISTCMD_previous=$(fc -l -1); HISTCMD_previous=${HISTCMD_previous%%$'[\t ]'*}
  if [[ -z $HISTCMD_before_last ]]; then
    # initial prompt
  elif [[ $HISTCMD_before_last = "$HISTCMD_previous" ]]; then
    # cancelled prompt
  else
    # a command was run
  fi
  HISTCMD_before_last=$HISTCMD_previous
}
PROMPT_COMMAND='prompt_command'

Lưu ý rằng nếu bạn đã bật tắt các bản sao trong lịch sử ( HISTCONTROL=ignoredupshoặc HISTCONTROL=erasedups), điều này sẽ báo cáo nhầm một lệnh trống sau khi chạy hai lệnh giống nhau liên tiếp.


Cảm ơn, Gilles. Tôi đang thiếu một cái gì đó ở đây. Điều này dường như không bao giờ chạy, vì đặt 'echo hello' trên dòng đầu tiên của chức năng nghĩa đen không hoạt động, mặc dù PROMPT_COMMAND = 'echo hello' thực hiện. Tôi nghĩ rằng nó có thể là vấn đề HISTCMD_preingly vs HISTCMD_PREVIOUS, nhưng không có xúc xắc. Tôi sẽ tiếp tục chọc, nhưng tôi đang bình luận vì bash fu của bạn rõ ràng là giải đấu vượt xa tôi.
người dùng

@user Tôi đã sửa nhiều lỗi chính tả hơn, đặc biệt là ${HISTCMD_previous%%$'[\t ]'*}bit bị thiếu $'…'và cuối cùng bị cắt bớt sau `, t` hoặc dấu cách thay vì sau tab hoặc dấu cách, nhưng bash in một tab.
Gilles 'SO- ngừng trở nên xấu xa'

1
Giải pháp này dựa trên giả định rằng các bản sao được lưu trong lịch sử (đó là TẮT cho tôi). Do đó giải pháp này không hoạt động như mong đợi cho các lệnh lặp đi lặp lại trong khi các bản sao không được lưu trong lịch sử.
schlimmchen

4

Có một cách giải quyết, nhưng nó có một số yêu cầu:

Bạn cần thiết lập $HISTCONTROLđể lưu TẤT CẢ các lệnh, cũng trùng lặp và khoảng trắng. Vì vậy, thiết lập:

HISTCONTROL=

Bây giờ xác định một hàm để gọi là $PROMPT_COMMAND:

isnewline () {
  # read the last history number
  prompt_command__isnewline__last="$prompt_command__isnewline__curr"
  # get the current history number
  prompt_command__isnewline__curr="$(history 1 | grep -oP '^\ +\K[0-9]+')"
  [ "$prompt_command__isnewline__curr" = "$prompt_command__isnewline__last" ] && \
    echo "User hit return"
}

Bây giờ, đặt $PROMPT_COMMANDbiến:

PROMPT_COMMAND="isnewline"

Xem đầu ra:

user@host:~$ true
user@host:~$ <return>
User hit return
user@host:~$ <space><return>
user@host:~$ 

Tôi không hiểu tại sao bạn sử dụng một tệp tạm thời ở đây. Biến lastđược bảo toàn từ một lần gọi isnewlinetiếp theo (chỉ chọn một tên ít chung chung hơn prompt_command__isnewline__lastđể tránh xung đột).
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles Bạn nói đúng, tôi đã thay đổi nó, cảm ơn vì lời đề nghị của bạn
sự hỗn loạn

Cảm ơn, hỗn loạn. Tôi đã sử dụng cùng một ý tưởng cho sau đây, dễ phân tích hơn một chút. HISTCONTROL="" function last_was_blank { local last_command="$(history 1)" if [[ "$last_was_blank_PREVIOUS_LINE" = "$last_command" ]] ; then echo "true" else echo "false" fi export last_was_blank_PREVIOUS_LINE="$last_command" } PROMPT_COMMAND=last_was_blank
người dùng

1

Tôi không biết cách nào để làm điều đó, mọi người ạ . Nhưng bạn có thể có được hiệu quả tương tự bằng cách sử dụng

bẫy some_command_or_function gỡ lỗi

Điều này sẽ khiến some_command_or_functioncho được gọi bất cứ khi nào bạn chạy một lệnh. Điều khó khăn là, nó sẽ không được gọi nếu bạn chỉ nhấn Enter- trừ khi bạn đã xác định PROMPT_COMMAND, trong trường hợp đó, việc Entergọi ra PROMPT_COMMAND, do đó, sẽ kích hoạt bẫy.

Có lẽ cách đơn giản nhất để đạt được kết quả mà bạn muốn là xác định hàm bẫy gỡ lỗi thay vì sử dụng PROMPT_COMMAND. Nhưng tôi không thể nói, vì tôi không biết kết quả mà bạn muốn. Nếu bạn muốn điều gì đó xảy ra khi bạn vừa nhấn Entervà điều gì đó khác / bổ sung sẽ xảy ra khi bạn nhập lệnh, thì (AFAIK) bạn cần sử dụng bẫy gỡ lỗi và PROMPT_COMMAND. Xem câu trả lời này và  câu trả lời này để biết cách làm cho hai cơ chế hoạt động tốt với nhau.


0

(Đây sẽ là một nhận xét cho câu trả lời được chấp nhận nếu tôi được phép thêm nhận xét ...) @schlimmen, bạn có thể đặt HISTTIMEFORMATthành một cái gì đó giống như HISTTIMEFORMAT='%F %T 'sau đó lưu và so sánh history 1. Đó là bởi vì với các lần xóa ít nhất là dấu thời gian của lệnh cuối cùng (có thể lặp lại) thay đổi mỗi lần --- và với HISSTIMEFORMATcài đặt phù hợp, history 1sẽ hiển thị dấu thời gian (không giống như fc), và do đó khác nhau ngay cả giữa các lệnh lặp lạ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.