Linux Shell 编程学习与实战

Breeze Shane大约 7 分钟MathematicsMathematics

模拟输入组合键Ctrl+AnyKey

上一篇笔记中我提到没能将输入内容送入指定的进程PID,但在了解到这一点之前我学到了如下的一些内容:

echo $$ # 这个是显示当前进程的PID。
echo $1 # 这个是表示执行脚本时输入的第1个参数

特别地,对于命令echo $'\<CODE>'有如下的对应:

  • \001 ==> Ctrl+A
  • \002 ==> Ctrl+B
  • \003 ==> Ctrl+C
  • \004 ==> Ctrl+D
  • \005 ==> Ctrl+E
  • \006 ==> Ctrl+F
  • \007 ==> Ctrl+G
  • \010 ==> Ctrl+H
  • \011 ==> Ctrl+I
  • \012 ==> Ctrl+J
  • \013 ==> Ctrl+K
  • \014 ==> Ctrl+L
  • \015 ==> Ctrl+M
  • \016 ==> Ctrl+N
  • \017 ==> Ctrl+O
  • \020 ==> Ctrl+P
  • \021 ==> Ctrl+Q
  • \022 ==> Ctrl+R
  • \023 ==> Ctrl+S
  • \024 ==> Ctrl+T
  • \025 ==> Ctrl+U
  • \026 ==> Ctrl+V
  • \027 ==> Ctrl+W
  • \030 ==> Ctrl+X
  • \031 ==> Ctrl+Y
  • \032 ==> Ctrl+Z

在写上面的映射表时我嫌一个一个打太麻烦,于是搜索了好多资料,最后成功使用了Shell命令来实现循环输出字符,执行:

paste <(seq 1 26) <(echo -e "A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nU\nV\nW\nX\nY\nZ") |  while read num char; do printf " - \`\%03o\` ==> <kbd>Ctrl</kbd>+<kbd>$char</kbd>\n" $num; done

该命令的含义是将数字1-26和字母A-Z分别一一绑定,输入到后面的while循环中的两个变量numchar,然后按照该格式打出,执行该命令后会得到这个输出:

 - `\001` ==> <kbd>Ctrl</kbd>+<kbd>A</kbd>
 - `\002` ==> <kbd>Ctrl</kbd>+<kbd>B</kbd>
 - `\003` ==> <kbd>Ctrl</kbd>+<kbd>C</kbd>
 - `\004` ==> <kbd>Ctrl</kbd>+<kbd>D</kbd>
 - `\005` ==> <kbd>Ctrl</kbd>+<kbd>E</kbd>
 - `\006` ==> <kbd>Ctrl</kbd>+<kbd>F</kbd>
 - `\007` ==> <kbd>Ctrl</kbd>+<kbd>G</kbd>
 - `\010` ==> <kbd>Ctrl</kbd>+<kbd>H</kbd>
 - `\011` ==> <kbd>Ctrl</kbd>+<kbd>I</kbd>
 - `\012` ==> <kbd>Ctrl</kbd>+<kbd>J</kbd>
 - `\013` ==> <kbd>Ctrl</kbd>+<kbd>K</kbd>
 - `\014` ==> <kbd>Ctrl</kbd>+<kbd>L</kbd>
 - `\015` ==> <kbd>Ctrl</kbd>+<kbd>M</kbd>
 - `\016` ==> <kbd>Ctrl</kbd>+<kbd>N</kbd>
 - `\017` ==> <kbd>Ctrl</kbd>+<kbd>O</kbd>
 - `\020` ==> <kbd>Ctrl</kbd>+<kbd>P</kbd>
 - `\021` ==> <kbd>Ctrl</kbd>+<kbd>Q</kbd>
 - `\022` ==> <kbd>Ctrl</kbd>+<kbd>R</kbd>
 - `\023` ==> <kbd>Ctrl</kbd>+<kbd>S</kbd>
 - `\024` ==> <kbd>Ctrl</kbd>+<kbd>T</kbd>
 - `\025` ==> <kbd>Ctrl</kbd>+<kbd>U</kbd>
 - `\026` ==> <kbd>Ctrl</kbd>+<kbd>V</kbd>
 - `\027` ==> <kbd>Ctrl</kbd>+<kbd>W</kbd>
 - `\030` ==> <kbd>Ctrl</kbd>+<kbd>X</kbd>
 - `\031` ==> <kbd>Ctrl</kbd>+<kbd>Y</kbd>
 - `\032` ==> <kbd>Ctrl</kbd>+<kbd>Z</kbd>

同时我也注意到,如果是使用了echo $'\1XX'的话还有如下的映射关系:

  • \101 ==> A
  • \102 ==> B
  • \103 ==> C
  • \104 ==> D
  • \105 ==> E
  • \106 ==> F
  • \107 ==> G
  • \110 ==> H
  • \111 ==> I
  • \112 ==> J
  • \113 ==> K
  • \114 ==> L
  • \115 ==> M
  • \116 ==> N
  • \117 ==> O
  • \120 ==> P
  • \121 ==> Q
  • \122 ==> R
  • \123 ==> S
  • \124 ==> T
  • \125 ==> U
  • \126 ==> V
  • \127 ==> W
  • \130 ==> X
  • \131 ==> Y
  • \132 ==> Z

类似地,上面这个映射表我也是使用了这个命令:

paste <(seq 1 26) <(echo -e "A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nU\nV\nW\nX\nY\nZ") |  while read num char; do printf " - \`\\\1%02o\` ==> $char\n" $num; done

这样有什么用?当你需要完成自动化交互的时候可以使用echo $<CODE> | XXX来将这样的值输入到后面的XXX中。

针对模拟输入组合键Ctrl+AnyKey的思考

经过不断地尝试echo $'\XXX' | $0这个命令来查看终端反应后我发现,上一节这个映射表其实绝非偶然,经过我的查证后才发现,实质上XXX是一个八进制数字,转换为对应的十进制后你应该会发现,每一个字母对应的十进制数值恰恰是我们熟悉的ASCII码,比如(101)8=(65)10(101)_8=(65)_{10},这正好就是A的ASCII码。

于是我去查询ASCII码表,并在这给出:

二进制八进制十进制十六进制字符/缩写解释
00000000000000NUL (NULL)空字符
00000001001101SOH (Start Of Headling)标题开始
00000010002202STX (Start Of Text)正文开始
00000011003303ETX (End Of Text)正文结束
00000100004404EOT (End Of Transmission)传输结束
00000101005505ENQ (Enquiry)请求
00000110006606ACK (Acknowledge)回应/响应/收到通知
00000111007707BEL (Bell)响铃
00001000010808BS (Backspace)退格
00001001011909HT (Horizontal Tab)水平制表符
00001010012100ALF/NL(Line Feed/New Line)换行键
00001011013110BVT (Vertical Tab)垂直制表符
00001100014120CFF/NP (Form Feed/New Page)换页键
00001101015130DCR (Carriage Return)回车键
00001110016140ESO (Shift Out)不用切换
00001111017150FSI (Shift In)启用切换
000100000201610DLE (Data Link Escape)数据链路转义
000100010211711DC1/XON (Device Control 1/Transmission On)设备控制1/传输开始
000100100221812DC2 (Device Control 2)设备控制2
000100110231913DC3/XOFF (Device Control 3/Transmission Off)设备控制3/传输中断
000101000242014DC4 (Device Control 4)设备控制4
000101010252115NAK (Negative Acknowledge)无响应/非正常响应/拒绝接收
000101100262216SYN (Synchronous Idle)同步空闲
000101110272317ETB (End of Transmission Block)传输块结束/块传输终止
000110000302418CAN (Cancel)取消
000110010312519EM (End of Medium)已到介质末端/介质存储已满/介质中断
00011010032261ASUB (Substitute)替补/替换
00011011033271BESC (Escape)逃离/取消
00011100034281CFS (File Separator)文件分割符
00011101035291DGS (Group Separator)组分隔符/分组符
00011110036301ERS (Record Separator)记录分离符
00011111037311FUS (Unit Separator)单元分隔符
001000000403220(Space)空格
001000010413321!
001000100423422"
001000110433523#
001001000443624$
001001010453725%
001001100463826&
001001110473927'
001010000504028(
001010010514129)
00101010052422A*
00101011053432B+
00101100054442C,
00101101055452D-
00101110056462E.
00101111057472F/
0011000006048300
0011000106149311
0011001006250322
0011001106351333
0011010006452344
0011010106553355
0011011006654366
0011011106755377
0011100007056388
0011100107157399
00111010072583A:
00111011073593B;
00111100074603C<
00111101075613D=
00111110076623E>
00111111077633F?
010000001006440@
010000011016541A
010000101026642B
010000111036743C
010001001046844D
010001011056945E
010001101067046F
010001111077147G
010010001107248H
010010011117349I
01001010112744AJ
01001011113754BK
01001100114764CL
01001101115774DM
01001110116784EN
01001111117794FO
010100001208050P
010100011218151Q
010100101228252R
010100111238353S
010101001248454T
010101011258555U
010101101268656V
010101111278757W
010110001308858X
010110011318959Y
01011010132905AZ
01011011133915B[
01011100134925C\
01011101135935D]
01011110136945E^
01011111137955F_
011000001409660`
011000011419761a
011000101429862b
011000111439963c
0110010014410064d
0110010114510165e
0110011014610266f
0110011114710367g
0110100015010468h
0110100115110569i
011010101521066Aj
011010111531076Bk
011011001541086Cl
011011011551096Dm
011011101561106En
011011111571116Fo
0111000016011270p
0111000116111371q
0111001016211472r
0111001116311573s
0111010016411674t
0111010116511775u
0111011016611876v
0111011116711977w
0111100017012078x
0111100117112179y
011110101721227Az
011110111731237B{
011111001741247C|
011111011751257D}
011111101761267E~
011111111771277FDEL (Delete)删除

你尽可以自己亲自验证。

关于其中一些控制符号的说明其实可以执行这个命令来查看stty -a,得到的输出是:

❯ stty -a
speed 38400 baud; rows 29; columns 119; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q;
stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc