• 高效操作Bash(快捷键和技巧)
    时间:2012-08-29   作者:极限手指   出处:ahei.info

    我们在平常工作中大量使用linux, 而使用linux的过程中操作Bash更是非常之频繁, 所以怎样高效的操作Bash是一个非常重要的问题. 下面我结合自己的经验总结一下高效操作Bash的一些技巧.

    1 快捷键

    1.1 注意

    本文的快捷键表示中, C 表示Ctrl键, M表示Alt健. 这些快捷键中, 有一个小规律, 对字符操作一般是C开头, 对单词操作一般是M开头. 如果你用SecureCRT, 默认的话, 会输入不了Alt开头的快捷键, 因为Alt被当作菜单快捷键了, 可以点 选项 -> 回话选项, 选择tab 终端->仿真->Emacs, 把”使用Alt键作为元键”打勾. 如果你用gnome-terminal, 默认状态下也输入不了Alt开头的快捷键,也被当作菜单快捷键了,可以点 编辑 -> 键盘快捷键, 把"启用菜单快捷键"前面的勾去掉.

    下面的快捷键中很多以Ctrl键开头, 很多键盘的Ctrl键并不是很好按, 可以尝试把Ctrl键和Capslock键交换.

    1.2 重度推荐

        C-r

        有时候,如果你想重新输入以前输入过的某条命令怎么办? 我见过两种做法:

            不停的按向上方向键,试图找出那条命令
            输入history命令,然后找到那条命令,或者grep一把history命令的输出

        其实, 你有更好的选择, 那就是按 C-r, 然后输入你想要的命令中含有的单词, 就会出现含有这个单词的命令, 如果它不是你想要的命令, 就继续按C-r, 知道出现你想要的命令为止. C-r效果:

        (reverse-i-search)`ls': ls a b c

        M-.

        我经常见别人用mkdir long-long-long-name-dir后, 再输入cd, 后面跟那个长的不能再长的目录名, 这时候我就会告诉他, 其实你输入完cd后, 可以按M-., 就可以自动输入那个长的不能再长的目录名了. 其实, M-.的真正作用就是把上一条命令的最后一个参数输入到当前命令行. 非常非常之方便, 强烈推荐. 如果继续按M-., 会把上上条命令的最后一个参数拿过来. 同样, 如果你想把上一条命令第一个参数拿过来咋办呢? 用M-0 M-., 就是先输入M-0, 再输入M-.. 如果是上上条命令的第一个参数呢? 当然是M-0 M-. M-.了.

    1.3 常用快捷键

        程序控制

        终止当前在前台运行的程序     C-c
        挂起当前在前台运行的程序     C-z
        如果光标在行首且当前行没有输入任何字符, C-d会退出当前会话     C-d

        光标移动

        向前(Forward)移动一个字符     C-f
        向后(Backward)移动一个字符     C-b
        向前移动一个单词     M-f
        向后移动一个单词     M-b
        移动光标到行首     C-a
        移动光标到行尾     C-e

        编辑

        向前删一个字符     C-d
        向后删一个字符     C-h
        向前删一个单词     M-d
        向后删一个单词, 单词之间以符号分割     C-M-h
        向后删一个单词, 单词之间以空格分割     C-w
        清屏, 相当于命令clear, 有了这个快捷键, 就不用每次努力的敲clear了     C-l
        删除当前光标到行尾的字符     C-k
        删除当前光标到行首的字符     C-u
        粘贴删除环里面的第一项     C-y
        粘贴删除环里面的后面的项     M-y
        undo     C-/
        取出上一条命令的最后一个参数     M-.

        对于C-M-h和C-w的区别, 看下面这个例子:

        如果当前光标前面的字符串为”abc def-ghi”, C-M-h会删掉ghi, 但是C-w会删掉”def-ghi”, 也就是说, C-M-h向后删的时候碰到非字母和数字就会停止, 但是C-w碰到空格才会停止.

        Bash下有一个删除环(kill-ring), 所有被删除的东西(用C-d删除的字符不算)都会进入这个环, C-y会粘贴环里面最近进去的项, 想要粘贴后面的项, 必须在按C-y后, 不停的按M-y, 直到出来你想要的项为止.

        有时候, 你想搜索某个文件中是否有TAB键, 你这时候会怎么做呢? 你或许会用grep, 在你输入完grep后, 你再按TAB, 这时候会出来什么? 什么都没出现! 再按? 出来:

        Display all N possibilities? (y or n)

        这是为何呢? 因为TAB是补全键. 那么是否是输入不了TAB吗? 不是! 按C-v后, 再按TAB即可. 同样, 想输入C-a, C-b也是同样的道理.

        历史命令操作

        从历史命令列表中取下一条命令, 相当于向下方向键     C-n
        从历史命令列表中取上一条命令, 相当于向上方向键     C-p
        向后增量搜索历史命令, 非常方便, 严重推荐, 有了它, 以前输入过的很长的命令, 可以不用重复输入     C-r
        循环执行历史命令     C-o

        用C-p取出历史命令列表中某一个命令后, 按C-o可以在这条命令到历史命令列表后面的命令之间循环执行命令, 比如历史命令列表中有50条命令, 后面三项分别是命令A, 命令B, 命令C, 用C-p取出命令A后, 再按C-o就可以不停的在命令A, 命令B, 命令C中循环执行这三个命令. C-o有一个非常好用的地方, 比如用cp命令在拷贝一个大目录的时候, 你肯定很想知道当前的拷贝进度, 那么你现在该怎样做呢? 估计很多人会想到不停的输入du -sh dir去执行, 但用C-o可以非常完美的解决这个问题, 方法就是:

            输入du -sh dir, 按回车执行命令
            C-p, C-o, 然后就可以不停的按C-o了, 会不停的执行du -sh dir这条命令

        其实上面这个问题也可以用watch命令解决:

        watch -n 1 -d du -sh dir

    1.4 高级快捷键

    从当前光标处向前搜索字符     C-]
    从当前光标处向后搜索字符     C-M-]
    交换当前光标下的字符和光标前面的一个字符, 交换后, 光标向后移东一个字符     C-t
    交换当前光标所在单词和光标前面一个单词, 交换后, 光标向后移动一个单词     M-t
    把单词首字符变成大写, 其他变成小写     M-c
    把单词变成小写     M-l
    把单词变成大写     M-u
    删除当前光标前面所有的空白字符     M-\
    向后非增量搜索历史命令     M-p
    相当于TAB健     C-i
    相当于回车键     C-m/C-j
    在当前光标处和上一次光标处不停的移动     C-x C-x

    1.5 总结

    其实, 上面所说的快捷键并不是由Bash来控制的, 而是有一个叫readline的库来控制的, readline库用在很多地方, 比如gdb, mysql, 你使用gdb的时候, 是不是很奇怪, 为啥它也能用上下方向键取出前面后面的命令? 因为它用的也是readline库. 所以只要掌握了readline, 就掌握了Bash, gdb, mysql等程序里面的快捷键操作技巧. readline是一个非常非常强悍的库, 它有两种模式, 一个是Emacs模式, 另外一个是vi模式, Emacs模式非常适合在命令行下使用, 我上面说的快捷键都是针对Emacs模式来说的. readline的Emacs模式下的光标移动, 编辑等快捷键和Emacs下的快捷键也非常相近. 所以你学会了这些快捷键, 也快入门Emacs了, :) . readline也可以自定义快捷键, 它还有一套配置语法. 关于它的详细介绍, 可以man readline或者info readline, 也可以看看大牛王垠写的readline介绍.


    2 历史扩展


    2.1 概念


    首先举个例子:

    首先输入一条命令:

    ls abc def ghi

    再输入:

    !!*:s/b/d

    那么实际上执行的命令是:

    adc def ghi

    我来解释一下, !!表示从命令历史列表中取上一条历史命令”ls abc def ghi”, *表示选择取刚才选择的命令的所有参数, 即: “abc def ghi”, :s/b/d表示对刚才取出来的参数”abc def ghi”进行替换, 把第一个出现的b替换成d

    从上面可以看出, 操作历史命令分为三步:

        首先从历史命令列表中选择某条命令, 被选择到的命令被称作 事件(event) (对应上面的!!)
        再从选择好的事件中选择一部分单词(words), 事件中的每个单词以空格分割(对应上面的*)
        最后对选择好的一部分单词进行修改(Modifiers)

    2.2 事件指示器(Event Designators)

    事件指示器用来从历史命令列表中选择一条命令, 也就是选择事件

        !n

        选择历史命令列表中第n条命令
        !-n

        选择倒数第n条命令
        !!

        选择上一条命令, 相当于!-1, 和 C-p 的作用也一样
        !string

        选择最近的以string开头的命令
        !?string[?]

        选择最近的包含string的命令, 如果该指示器后面是换行符, 则可以不用输入结尾的”?”
        ^string1^string2

        取上一条命令, 并把第一个出现的string1替换成string2
        !#

        引用目前输入的所有命令, 比如输入:

        more a !#

        那么最终执行的命令就是:

        more a more a

    2.3 单词指示器(Word Designators)

    单词指示器用来从被选择好的事件中选择一部分单词, 单词指示器必须以冒号(:)和事件指示器分割开来, 除非单词指示器以^, $, *, -, %开头

        0

        选择第0个word, 也就是命令. 假如事件为”ls abc”, 那么单词指示器0选择的word即为”ls”

        n

        选择第n个word
        ^

        选择命令的第一个参数, 也就是第一个word, 相当于单词指示器1

        $

        选择命令的最后一个参数

        %

        选择最近的与 “?string?” 搜索相匹配的单词

        x-y

        选择第x到第y个word, -y表示0-y

        *

        选择命令的所有参数, 相当于1-$

        x*

        x-$的缩写

        x-

        类似x*, 不过不包含最后一个word. -选择除最后一个word外所有的words

    2.4 修饰符(Modifiers)

    对选择的单词进行修改, 修饰符可以出现多次, 每个修饰符要以冒号开头

        p

        打印新命令, 但不执行
        s/old/new/
        把 第一次出现的 old替换成new, 如果分隔符”/”是最后一个字符的话, 可以省略. 就像sed中一样, 分隔符”/”可以用其他字符代替, 比如s:old:new:. new中出现的&将被old代替. 如果old省略, 那么就用上一次替换用的old代替.

        &

        重复上一次替换

        g

        使修饰符所做的修改应用于整个选择的单词. 类似于sed中的s命令最后的g, 可配合:s和:&修饰符使用, 比如:gs/old/new则对整个事件进行替换.

        a

        和g作用一样

        G

        使后面的:s修饰符对每个word只替换一次

    2.5 例子

        例一

        从别的机器的一个目录拷贝一个a.log文件, 执行:

        scp user@machine:/home/user/a/a.log .

        后来执行:

        ls a.log
        rm -rf a.log

        这时候再想拷贝一下b/b.log, 这时候就可以这样做:

        !scp:gs/a/b

        如果只想看看用历史扩展出来的命令, 那可以这样:

        !scp:gs/a/b/:p

        例二

        从别的机器同时拷贝a/a.log和b/b.log:

        scp user@mbchine:/home/user/a/a.log . && !#-:gs/a/b

        上面的!#为事件指示器, 选择前面已经输入的命令”scp user@mbchine:/home/user/a/a.log . &&”, “-”为单词指示器, 选择除最后一个word, 即”&&”外的所有words, 也就是”scp user@mbchine:/home/user/a/a.log . “, 最后的”:gs/a/b”为修饰符, 对刚才选择的words进行全局替换, 把a替换成b, 最后就成了”scp user@mbchine:/home/user/b/b.log .”, 那么最终命令也就成了”scp user@mbchine:/home/user/a/a.log . && scp user@mbchine:/home/user/b/b.log .”

    2.6 总结

    上面的例子都可以用前面所说的快捷键完成, 不过灵活利用历史扩展有时候还是能更高效的完成同样的事情

    3 shell技巧

    3.1 Here Documents

    <<[-]word
    here-documents
    delimiter

    把here-documents作为某个命令的标准输入, 例子:

    grep a << EOF
    asdf
    qweszd
    asdf
    EOF

    3.2 Here Strings

    <<< here-strings

    把word作为命令的标准输入, 例子:
    grep a <<< abc

    3.3 进程替换(Process Substitution)

    假如我现在想比较两个目录dir1和dir2中的文件有啥不同, 我想很多人会这样做:

    ls dir1 > 1
    ls dir2 > 2
    diff 1 2

    但你试试这样:

    diff <(ls dir1) <(ls dir2)

    是不是也可以? 很神奇吧. 上面的这个语法<(command)就是进程替换. <(command)表示把command的输出生成一个临时文件, 并把这个文件名作为另外一个命令的参数. 对于上面的命令, 就是把”ls dir1″命令的输出生成一个临时文件, 并把临时文件名做为diff命令的第一个参数. 再举一个例子:

    wget -q -O >(cat) http://www.kaiyuanba.cn

    wget命令会把下载后的文件保存到文件中去, 但是我们可以用上面的命令不让它保存到文件中去, 而是显示出来. wget的”-O”选项后本来应该是一个文件名的参数, 但是我们现在用>(cat)代替, 表示wget下载下来的内容放到一个临时文件中, 然后把这个临时文件名再传给>()里面的cat命令.
    灵活运用进程替换, 将会非常的方便, 严重推荐

    网友留言/评论

    我要留言/评论

    相关文章

    Ubuntu 配置之WebDav服务器:什么是WebDAV?简单地说:“基于Web的分布式创作和版本”的WebDAV。它是HTTP协议,它允许用户协作编辑和管理远程Web服务器上的文件的扩展。听说苹果的icloud 也是基于webdav来实现的,使用Ubuntu 如何配置webdav服务器呢?
    Linux操作系统使用的几个小窍门:如果你是Linux初学者,这几个技巧将对你非常有帮助哦,即使老手也可能不知道的小知识,不容错过。
    Linux 下 OpenVPN和Windows OpenVPN GUI安装笔记:基于伟大的 GFW 越来越牛B,网站的正常维护如 FTP、pop & smtp 的邮件收发、在 google 查技术资料,都经常被 GFW 强行断开。为了解决这个问题,于是我在自己的国外主机上安装了一个 OpenVPN,当时记录了一下安装的经过。感谢原作者小辉。
    Bash的24个陷阱分析:今天想分析的是这篇Bash Pitfalls, 介绍了一些bash编程中的经典错误。fcicq说可能不适合初学者,而我认为,正是bash编程的初学者才应该好好阅读一下这篇文章。 下面就逐个分析一下这篇文章中提到的错误。不是完全的翻译,有些没用的话就略过了,有些地方则加了些注释。
    Shell中对于Find查到的文件处理小结:本文对Shell中对于Find查到的文件处理小结,以作备用
    编译maplayer遇到fontconfig问题的解决方法:在网上看到过很多朋友安装mplayer或者qt的时候报undefined reference to `FcFreeTypeQueryFace'错误,恰好我也碰到了,发一下我的解决方法,以给朋友们共享。
    学会使用Linux性能分析工具:Linux在具有高稳定性、可靠性的同时,具有很好的可伸缩性和扩展性,能够针对不同的应用和硬件环境调整,优化出满足当前应用需要的最佳性能。因此企业在维护Linux系统、进行系统调优时,了解系统性能分析工具是至关重要的。