`
totoxian
  • 浏览: 1074285 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

快捷键和控制序列--bash的命令行编辑原理以及其它杂述

 
阅读更多

对于整天在命令行下工作的家伙来说,命令行编辑功能的强弱直接关系到了工作效率,试想如果一个命令行很长很长,写到最后发现很靠前的一个地方写错了,需要修改,此时如果按方向键的话还不累死,因此对于shell来说,非常需要一种行编辑功能,可以在一行当中快速定位。bash就提供了这样的功能,可惜知道这一点的人比较少。首先来有个感性认识,熟悉几个简单且常用的快捷键(每个快捷键都会发送一个键序列,然后shell会解释这个序列然后作出答复)
Ctrl-A:将光标移动到行首
Ctrl-T:交换光标前面的两个字符,可以在命令行模拟冒泡排序
Ctrl-L:clear 清屏
Ctrl-N:删除本行
Ctrl-E:将光标移动到行尾
Ctrl-K:删除从光标到行尾的内容
Ctrl-U:删除从光标到行首的内容
Ctrl-W:删除左边的词
Ctrl-Y:撤消 Ctrl-U Ctrl-K Ctrl-W
Tab:命令补全
Ctrl-R:在命令历史中增量查找
在SecureCRT中增加一个键映射的方式是:
会话选项:终端-仿真-映射键
点击“映射一个键”后出现一个小小对话框,让你使用键盘输入,输入ctrl+f,然后SecureCRT会让你输入你输入刚才的那个组合键时需要发送的字符串,此时就要看一下bash(注意,不是vt100的手册或者别的终端的手册)的手册了,以光标向右移动一个单词为例,bash要求发送ESC+F,那么此时就输入要发送的字符串是"/033f",然后保存,试一下刚刚设置的键映射,在命令行上写一行空格分隔的字符串:ab cd ef,把光标置于行首,按下ctrl+b,看看是不是光标前移了一个单词,实际上更直接的,你可以直接输入ESC键,然后输入f键。
实际上完全可以不使用ctrl键,直接输入一个f就将光标forward一个单词,只是那样的话如果你想输入字符"b"的话就需要另外想办法了,正如vi/vim那样,输入一个i就进入插入模式,输入esc就退出插入模式,实际上就是更改了键映射(keymap),在命令行也可以这么干的,只是复杂了一些(参考bash的VI_MODE)。总之,编辑命令行的方式是可以定制的,按照自己的习惯设置不同的键盘按键和bash内置的命令序列的映射即可,bash内置的的命令序列是什么,是以ctrl或者esc打头,也就是/01或者/033或者/x1b打头的字符串,后面跟什么?看bash的源码!如果没有我需要的怎么办?自己修改代码自己添加!
bash中的emacs_keymap.c是一个很重要的文件,bash默认的将keymap设置成了emacs的keymap,其中emacs_standard_keymap和emacs_meta_keymap是两个至关重要的结构体,它们都是KEYMAP_ENTRY的实例组成的数组,KEYMAP_ENTRY的定义如下:
typedef struct _keymap_entry {
char type;
Function *function;
} KEYMAP_ENTRY;
数组的下标和键序列一一对应,而function指示bash在接收了这个键序列后的行为,其实就是将bash的控制键序列转化为终端的控制键序列,然后写入终端,比如bash定义的ctrl+L键是清屏,bash收到该键后会写入一个vt100的esc的键序列/033[2J来完成清屏(使用vt100兼容终端的情况下)。到此大家应该都明白,快捷键序列是终端发给shell的,而终端控制序列(比如vt100的esc控制序列)是shell发给终端的,shell可以在快捷键和终端序列之间做映射,做转化,shell做了转化后,原先的快捷键就有可能被解释成了vt100的控制序列,比如ctrl+l快捷键被bash解释成了'/033[2J',然后bash将后者写回终端,结果就是终端清屏。
如果自己希望的功能在bash中没有被定义怎么办呢?办法就是修改bash,在emacs_standard_keymap数组中添加一个元素,然后将处理回调函数定义成自己希望的vt100功能,比如可以为“将光标定位到特定的位置,即'/033[x;yH'定义一个元素,该元素的回调函数为向终端回写到终端。值得注意的是,所谓的终端控制序列只在终端的所在地起作用,在linux主机上只负责处理逻辑和终端伪终端的请求,这和X Server是一样的,显示只在server端进行,client端只负责告诉server如何显示,类比终端的情形,一个远程终端就相当于一个X server,只是功能弱些罢了,虽然主机通过发送vt100控制序列要求终端做一些动作,比如移动光标,清屏,切换字符集等等,但是终端完全可以自己解释这些控制序列然后作出完全不同或者不合逻辑的行为,还记得linux终端的乱码问题吗?通过设置终端字符集可以使终端乱码,比如echo -ne '/033(0' && echo -ne '/033)0'这个命令写入了/dev/pts/X,控制序列进入pts/X从/dev/ptmx被sshd读出,然后通过socket发送到远端,远端就乱码了,可是通过strace -p [sshd的pid]或者ssh不加密情况下抓包发现,直到sshd将数据从ptmx读出,数据都不是乱码,sshd只是将数据加密,由此可见,数据是到了终端这边才乱掉的,也就是说,“设置字符集”这件事只是一个命令,只有它到了实际终端才会被执行,如果修改一下终端的代码,忽略掉这个命令或者曲解它都可以,这就是将在外,君命有所不受。控制序列在从写入/dev/pts/X到远程(或者本地)终端接收到的过程中,它只是一个命令而已,具体执行不执行以及如何执行完全取决于终端本身。
所以在linux内核的pty驱动中没有发现任何的对控制序列的解释,可是在vc(vitrua console)的驱动中却有完整的解释,do_con_trol中就解释了很多的控制序列,ESsetG0和ESsetG1两个字符集的切换全在内部执行,这是因为虚拟终端本身就在本机(就是开机后的那些可以通过alt+Fx切换的黑色屏幕),因此像/dev/ttyX之类的虚拟终端内部必须包含对控制序列的执行。
vt100兼容终端中,除了esc-控制序列外,ctrl+v也会开启一个控制命令,比如切换G0和G1的命令就是ctrl+v/ctrl+o/n来发出的,其命令就是0a0e/0a0f,将之用echo -ne写入一个终端就会切换该终端的字符集,写入的时候,直接将0a0e或者0a0f作为命令写入,这两个字节到了实际终端的时候,终端解释之,执行之,切换字符集...如果终端忽略了它们呢?很简单,那就不切换字符集。如果理解了X系统,那么可以反过来加深对终端的理解,虽然终端早在X系统之前很久就出现了,X系统之所以出现本身就是为了弥补字符终端的不足,字符终端太单调了,其实X服务器有时候也被称作X终端,有的X终端对X客户端发来的命令就不是原样执行的,事实上每一个X终端都会在遵循协议规范的前提下自主解释并执行x客户端的命令,可能会加入一些自己扩展的东西,这也就解释了为何有的x终端很绚。
vi和bash一样,本质上也包含了一个按键解释器(和emacs_standard_keymap,emacs_meta_keymap类似),这就是为何可以通过esc来切换模式的原因,esc按键或者i按键会触发解释器的切换,从命令模式切换到插入模式或者相反。vi其实和vt100终端控制序列关系不大,它只是一个带有缓冲区的按键解释器而已,它可以将按键在使用vt100终端的情况下解释成vt100的序列,也可以在使用windows系统的情况下解释成windows的GDI函数调用,总之,你的输入是键输入,不要指望你总可以输入一个终端控制序列(除非echo -ne或者一些特殊情况),键输入相当于一个请求,shell或者别的应用程序接收到这个键请求后会根据你的终端类型发送控制命令,这个控制序列指导你的终端如何反应,键在终端本地发出,和本地关联--windows?linux?,而控制命令序列则由主机shell发出,最终由终端本地执行,vt100以esc作为序列开头码完全是为了方便,之所以你输入esc然后输入b(或者发送/033b)会回退一个单词,这和vt100的esc序列丝毫没关系,这是因为你的shell解释了这个esc+b快捷键。

分享到:
评论

相关推荐

    Bash Quick Reference

    - **说明**:提供了对后台运行的任务进行管理和控制的能力。 ##### 17. Options to set(设置选项) - **位置**:第22页 - **说明**:列出了可以设置的各种选项及其作用。 ##### 18. Options to shopt(shopt选项...

    Linux中shell(bash)的简单模拟。___下载.zip

    2. **命令行编辑**:bash支持使用箭头键进行命令历史的上下滚动,以及通过Ctrl+U、Ctrl+K等快捷键进行文本剪切和粘贴,提高输入效率。 3. **通配符和文件名扩展**:`*`和`?`是常用的通配符,`*`代表任意多个字符,`...

    ConEmu_取代cmd的命令行控制台ComEmu.zip

    ConEmu是一款强大的Windows命令行工具,它旨在替代传统的cmd.exe控制台,提供更为高效、功能丰富的命令行环境。这款工具不仅支持ansi颜色,还具备多窗口管理、自定义配色方案、高度可配置性以及与各种终端模拟器的...

    readline-6.1

    - **命令行编辑**:支持上下箭头浏览历史记录,Ctrl+R逆向搜索历史,以及各种编辑快捷键。 - **补全功能**:可以实现基于文件名、命令、变量等的自动补全。 - **宏定义**:允许用户定义和保存命令序列,方便重复执行...

    debian参考手册——中文版

    - **设备文件**:Linux将硬件设备抽象为文件,用户可以通过这些文件来访问和控制硬件设备。 - **特殊设备文件**:包括字符设备和块设备,前者用于没有物理地址空间的设备(如终端),后者用于有物理地址空间的设备...

    Unix及Shell_基础

    0. Unix 介绍 Unix 是一种操作系统,诞生于1969年,由肯·汤普逊和丹尼斯·里奇在贝尔实验室开发。...熟练掌握这些知识,不仅可以提升日常工作效率,也是深入理解操作系统原理和自动化运维的基础。

    bash shell内建命令

    在深入探讨bash shell内建命令之前,我们先来理解一下bash是什么以及为什么它对更好地掌握Linux至关重要。Bash,全称Bourne-Again SHell,是Unix和类Unix操作系统中最常用的shell之一,包括所有主要的Linux发行版。...

    readline-5.1.tar.gz

    这个库使得程序能够支持历史记录、编辑功能以及通过键盘快捷键来增强用户的交互体验。 在 Linux 和类 Unix 系统中,`.tar.gz` 文件是常见的归档和压缩格式,由 `tar` 工具用来打包多个文件和目录,然后用 `gzip` ...

    Node.js-terminal-link-cli在终端中创建可点击的链接

    当你在终端运行包含该库的脚本时,链接将以高亮的形式显示,用户可以通过鼠标或特定的键盘快捷键来激活这些链接,打开浏览器或者执行其他操作。 使用 `terminal-link-cli` 非常简单。首先,你需要安装 Node.js 和 ...

    68个Linux内部命令用法简介

    这三条命令均属于GNU bash shell的一部分,并运行于GNU/Linux环境下。以下是针对每个命令的详细介绍: #### 1. alias - 定义或显示别名 **功能描述:** `alias` 命令用于定义或显示别名。别名是一种简化命令输入的...

    ubuntu入门到精通pdf

    - **w:** 显示当前登录的用户、他们所在的终端以及CPU和内存使用情况。 - **who:** 显示当前登录的所有用户。 - **whoami:** 显示当前用户的名字。 - **last:** 显示用户最近的登录记录。 - **uname:** 显示...

    bashscripts:我的bash个人资料和脚本

    它支持命令行操作、脚本编程,提供了丰富的内置命令和控制结构。 2. **Dotfiles详解**:在Unix-like系统中,以"."开头的文件是隐藏文件,常用于存储用户的个性化设置。例如,`.bashrc`文件在启动一个新的Bash shell...

    Cmder - Version 1.3.18(2021-03-26).7z

    3. **方便的快捷键和命令别名**:Cmder支持自定义快捷键和命令别名,提高了命令行操作的效率。例如,你可以设置快捷键来快速打开经常使用的目录或者执行复杂的命令序列。 4. **历史记录和搜索**:Cmder具有命令历史...

    linux配置文件

    对于Shell,可以查阅`man bash`获取关于Bash shell的详细信息,以及如何配置提示符和其他特性。 总之,这个“linux配置文件”压缩包中包含的是用户个性化的Vim编辑器和Shell终端设置,这些设置能够提高工作效率,但...

    Test5:命令行中的Test5项目

    4. **映射和自动化**:通过Vimscript定义键盘映射,将复杂的操作序列绑定到快捷键上,实现快捷的文本编辑和代码导航。 5. **Vim插件开发**:了解如何构建和安装Vim插件,以及插件系统的运作机制。 6. **Vim配置**...

    Python-xkeysnail是X环境的另一个键盘重新映射工具

    1. **编程**: 在编程环境中,可以为常用编辑操作(如复制、粘贴、查找替换)设置快捷键,提高效率。 2. **多媒体控制**: 自定义媒体播放器的控制键,如快进、快退、暂停/播放等。 3. **多语言输入**: 针对不同的...

    bash_shell内建命令和保留字

    Bash Shell 是Linux系统中最常用的命令行解释器,它的强大在于其丰富的内建命令和保留字,这些元素构成了用户交互的基础。内建命令是直接在Shell内部执行的,不需要启动额外的进程,效率较高;而保留字则在脚本或...

Global site tag (gtag.js) - Google Analytics