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?
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:
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_COMMAND
chí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=ignoredups
hoặ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.
${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.
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_COMMAND
biến:
PROMPT_COMMAND="isnewline"
Xem đầu ra:
user@host:~$ true
user@host:~$ <return>
User hit return
user@host:~$ <space><return>
user@host:~$
last
được bảo toàn từ một lần gọi isnewline
tiếp theo (chỉ chọn một tên ít chung chung hơn prompt_command__isnewline__last
để tránh xung độ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
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_function
cho đượ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.
(Đâ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 HISTTIMEFORMAT
thà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 HISSTIMEFORMAT
cài đặt phù hợp, history 1
sẽ 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.