如果按下向上/向左箭头键,是否可以在bash脚本中使用箭头键来运行某组命令,如果按下向下/向右箭头键,是否可以运行某个设置?我正试图通过使用箭头键在显示数据时快速切换用户,使用此脚本从中读取数据。
function main() # The main function that controls the execution of all other functions
{
mkdir -p ~/usertmp # Make a new temporary user directory if it doesn't exist
touch ~/last_seen_output.txt # Create the output file if it doesn't exist
cat /dev/null > ~/last_seen_output.txt # Make sure that the output file is empty
gather # Call the "gather" function
total=$((`wc -l ~/usertmp/user_list.txt|awk '{print $1}'`-1)) # Calculate the total amount of lines and subtract 1 from the result
echo Current Time: `date +%s` > ~/last_seen_output.txt # Print the current time to the output file for later reference
echo "" > ~/last_seen_output.txt # Print a blank line to the output file
if [ $log -eq 1 ]
then
# If it is enabled, then delete the old backups to prevent errors
while [ $line_number -le $total ]
do
line_number=$((line_number+1)) # Add 1 to the current line number
calculate # Call the "calculate" function
hms # Call the "hms" function to convert the time in seconds to normal time
log
done
else
while [ $line_number -le $total ]
do
line_number=$((line_number+1)) # Add 1 to the current line number
calculate # Call the "calculate" function
hms # Call the "hms" function to convert the time in seconds to normal time
echo "Displaying, please hit enter to view the users one by one."
read # Wait for user input
if [ "$log_while_displaying" ]
then
log
display
else
display
fi
done
fi
}
https://github.com/jbondhus/last-seen/blob/master/last-seen.sh是完整的脚本。
读取命令注释为“等待用户输入”是您输入以转到下一个用户的命令。基本上,这个脚本的用途是列出用户以及自每个用户登录以来所经过的时间。我正在尝试使用箭头键在显示的每个用户之间切换。我认为可以使用case语句来表示键输入。重申我的观点,我不确定这是否可行。如果不是,那么有人可以想到另一种方法吗?
答案 0 :(得分:14)
如前所述,光标键产生三个字节 - 而像home / end这样的键甚至会产生四个字节!我在某处看到的解决方案是让初始的one-char read()跟随三个后续的one-char读取,并且超时很短。最常见的键序列可以像这样显示:
#!/bin/bash
for term in vt100 linux screen xterm
{ echo "$term:"
infocmp -L1 $term|egrep 'key_(left|right|up|down|home|end)'
}
此外,/ etc / inputrc包含一些带有readline映射的内容。 所以,回答原始问题,这是一个剪辑,从那个bash菜单我只是在黑客攻击:
while read -sN1 key # 1 char (not delimiter), silent
do
# catch multi-char special key sequences
read -sN1 -t 0.0001 k1
read -sN1 -t 0.0001 k2
read -sN1 -t 0.0001 k3
key+=${k1}${k2}${k3}
case "$key" in
i|j|$'\e[A'|$'\e0A'|$'\e[D'|$'\e0D') # cursor up, left: previous item
((cur > 1)) && ((cur--));;
k|l|$'\e[B'|$'\e0B'|$'\e[C'|$'\e0C') # cursor down, right: next item
((cur < $#-1)) && ((cur++));;
$'\e[1~'|$'\e0H'|$'\e[H') # home: first item
cur=0;;
$'\e[4~'|$'\e0F'|$'\e[F') # end: last item
((cur=$#-1));;
' ') # space: mark/unmark item
array_contains ${cur} "${sel[@]}" && \
sel=($(array_remove $cur "${sel[@]}")) \
|| sel+=($cur);;
q|'') # q, carriage return: quit
echo "${sel[@]}" && return;;
esac
draw_menu $cur "${#sel[@]}" "${sel[@]}" "$@" >/dev/tty
cursor_up $#
done
答案 1 :(得分:8)
# This will bind the arrow keys
while true
do
read -r -sn1 t
case $t in
A) echo up ;;
B) echo down ;;
C) echo right ;;
D) echo left ;;
esac
done
答案 2 :(得分:6)
您可以使用read -n 1
读取一个字符,然后使用case
语句根据密钥选择要执行的操作。
问题是箭头键输出多个字符,序列(及其长度)因终端而异。
例如,在我正在使用的终端上,右箭头输出^[[C
。您可以按 Ctrl - V 右箭头查看终端输出的顺序。其他光标控制键也是如此,例如 Page Up 和 End 。
相反,我建议使用<
和>
这样的单字符键。在脚本中处理它们会简单得多。
read -n 1 key
case "$key" in
'<') go_left;;
'>') go_right;;
esac
答案 3 :(得分:6)
不确定这是否直接回答了问题,但我认为这是相关的 - 我在那些代码来自哪里徘徊,我终于找到了:
起初读起来有点困难;对于左箭头,在“Key”列中查找“LEFT 4”,对于bash
看到的序列,查找第5个(“keymap” - “normal”)列,其中写为“[ D 1b 5b 44“ - 表示该密钥的三个字节(27,91,68)。
找到线程How to read arrow keys on really old bash? - The UNIX and Linux Forums,激励我写一个简短的单行代码,它会转储按下的键的密钥代码。基本上,你按一个键,然后按Enter键(触发结束read
),然后使用hexdump
输出read
保存的内容(最后点击Ctrl-C退出循环):
$ while true; do read -p?; echo -n $REPLY | hexdump -C; done
?^[[D
00000000 1b 5b 44 |.[D| # left arrow
00000003
?^[[C
00000000 1b 5b 43 |.[C| # right arrow
00000003
?^[[1;2D
00000000 1b 5b 31 3b 32 44 |.[1;2D| # Shift+left arrow
00000006
?^[[1;2C
00000000 1b 5b 31 3b 32 43 |.[1;2C| # Shift+right arrow
00000006
?^C
因此,虽然箭头键需要3个字节 - Shift +箭头键需要6个!但是,看起来所有这些序列都以0x1b(27)开头,所以在读取任何更多字节之前,可能会检查read -n1
的这个值。同样5b
仍然是上表中“normal”和“shift / NUM-Lock”列的多字节序列中的第二个字节。
编辑:在Linux中扫描按键的终端代码更简单,更正确的方法是showkey:
$ showkey
Couldn't get a file descriptor referring to the console
$ showkey -h
showkey version 1.15
usage: showkey [options...]
valid options are:
-h --help display this help text
-a --ascii display the decimal/octal/hex values of the keys
-s --scancodes display only the raw scan-codes
-k --keycodes display only the interpreted keycodes (default)
$ sudo showkey -a
Press any keys - Ctrl-D will terminate this program
^[[A 27 0033 0x1b
91 0133 0x5b
65 0101 0x41
^[[B 27 0033 0x1b
91 0133 0x5b
66 0102 0x42
^[[A 27 0033 0x1b
91 0133 0x5b
65 0101 0x41
^[[D 27 0033 0x1b
91 0133 0x5b
68 0104 0x44
^[[C 27 0033 0x1b
91 0133 0x5b
67 0103 0x43
^C 3 0003 0x03
^M 13 0015 0x0d
^D 4 0004 0x04
答案 4 :(得分:6)
您可以在没有任何异常命令的情况下读取箭头键和其他键;你只需要两个read
来电,而不是一个:
escape_char=$(printf "\u1b")
read -rsn1 mode # get 1 character
if [[ $mode == $escape_char ]]; then
read -rsn2 mode # read 2 more chars
fi
case $mode in
'q') echo QUITTING ; exit ;;
'[A') echo UP ;;
'[B') echo DN ;;
'[D') echo LEFT ;;
'[C') echo RIGHT ;;
*) >&2 echo 'ERR bad input'; return ;;
esac
答案 5 :(得分:0)
使用replace
答案我想我为您提供了一个很好的解决方案。
其输出与eMPee584
答案大致相同,但不会由Shift键触发,并且可以在大多数终端中使用。
它具有UP DOWN LEFT RIGHT HOME和END键
这主要归功于user3229933
eMPee584
答案 6 :(得分:0)
扩展JellicleCat的答案:
#!/bin/bash
escape_char=$(printf "\u1b")
read -rsn1 mode # get 1 character
if [[ $mode == $escape_char ]]; then
read -rsn4 -t 0.001 mode # read 2 more chars
fi
case $mode in
'') echo escape ;;
'[a') echo UP ;;
'[b') echo DOWN ;;
'[d') echo LEFT ;;
'[c') echo RIGHT ;;
'[A') echo up ;;
'[B') echo down ;;
'[D') echo left ;;
'[C') echo right ;;
'[2~') echo insert ;;
'[7~') echo home ;;
'[7$') echo HOME ;;
'[8~') echo end ;;
'[8$') echo END ;;
'[3~') echo delete ;;
'[3$') echo DELETE ;;
'[11~') echo F1 ;;
'[12~') echo F2 ;;
'[13~') echo F3 ;;
'[14~') echo F4 ;;
'[15~') echo F5 ;;
'[16~') echo Fx ;;
'[17~') echo F6 ;;
'[18~') echo F7 ;;
'[19~') echo F8 ;;
'[20~') echo F9 ;;
'[21~') echo F10 ;;
'[22~') echo Fy ;;
'[23~') echo F11 ;;
'[24~') echo F12 ;;
'') echo backspace ;;
*) echo $mode;;
esac
答案 7 :(得分:0)
以上答案均未对我有用!我不得不从这个线程中的许多答案以及通过Google进行的其他搜索中获取点点滴滴。我花了大约一个小时来炮制这个。
我正在运行Ubuntu 20.04 LTS,这对我有用(尽管它可能并不完美,因为我必须对其进行“破解”):
waitkey() {
local end=""
local key=""
echo
echo " Press ESC ... "
while [ "$end" == "" ]; do
read -rsn1 key
case "$key" in
$'\x1b')
local k=""
# I'm not sure why I have to do this if statement,
# but without it, there are errors. took forever
# to figure out why 'read' would dump me outta the script
if [ "$IFS" ]; then
read -rsn1 -t 0.1 holder && k="$holder"
else
IFS=read -rsn1 -t 0.1 holder && k="$holder"
fi
if [ "$k" == "[" ]; then
read -rsn1 -t 0.1 holder && kk="$holder"
##############################
# you put your arrow code here
#
# eg:
# case "$kk" in
# "A") echo "up arrow!" ;; # do something ...
# esac
##############################
elif [ "$k" == "O" ]; then
read -rsn1 -t 0.1 holder && kk="$holder"
# I am honestly not knowing what this is for
elif [ "$k" == "" ]; then
end=1
fi
esac
done
}