Vim KeyMapper CMD

Vim模式

Normal模式

Insert模式

Visual模式

Quickfix模式

quickfix模式主要思想时保存一个位置列表,然后提供一系列命令, 实现在这个位置列表中的跳转

  • 位置列表来源

    • 编译器输出信息
    • grep命令输出信息(cscope命令)
    • :vimgrep命令
  • quickfix中常用的命令有

    • :copen/:cw:打开quickfix模式窗口
    • :cclose:关闭quickfix窗口
    • :cc:显示详细错误信息
    • :cp:跳至下一个错误
    • :cn:跳至上一个错误
    • :cl:列出所有错误
    • :cw:如果有错误列表,则打开quickfix窗口
    • :colder/col:到前一个旧错误列表
    • :cnewer/cnew:到后一个新错误列表

Ex模式

底层编辑模型,normal下Q进入

Paste模式

Motion快捷键

normal模式下移动,visual模式下选取,无特殊说明visual和normal 模式通用

固定移动

基本

  • hjkl:左、上、下、右
  • gj/gk:虚上、虚下(光标移动排版意义上行) (可以尝试noremap交换和j/k的逻辑方便使用)
  • M:窗口中间行首各非空白字符
  • H/L:窗口顶/底scrolloff处行首各非空白字符
  • <c-i>/<c-o>:跳至下一个/上一个编辑处 (可以跨文件)

行内

  • w:下个单词开头
  • aw:整个单词
  • b/e:当前单词首/尾
  • W/B:下/上个非空格开头
  • E: 下个非空格结尾
  • g_:行尾,visual模式下不包括换行符
  • $:行尾,visual模式下包括换行符
  • 0:行首
  • ^:非空白字符行首
  • |:当前行第一列
  • <int>|:当前行第n列(不是字符)

全文

  • gg:文件首
  • G:文件尾
  • <int>G:第<int>
  • '<:之前visual模式选取起始行(一直保存直至下次选取)
  • '>:之前visual模式选取结束行
  • {/}:下/上一个空行
  • .:当前行
  • %:全文选取???

组合

这些快捷键的效果取决于当前状态

行内

  • f/F:向前/后移动到某字符(;,同向、反向重复)
  • t/T:till,向前/后移动到某字符前
  • i:在某个区域((), [], {}, w等)内(显然不能单独用 于normal)

全文

  • //?:命令行向前、向后查找(nN同向、反向重复)
  • */#:向前、向后查找当前单词
  • g*/g#:向前、向后查找当前字符串,包括非单独单词

Operation快捷键

区域进行操作可以和motion连用

内容修改

插入

  • i:insert进入insert模式
  • I(normal):行首insert进入insert模式
  • I(visual block):选中区域同时插入
  • a:add进入insert模式
  • A:行尾add进入insert模式
  • <c-e>:insert模式下复制下行当前位置字符至当前行

删除

  • d:删除选取区域
  • c:删除(修改)选中区域,进入insert模式
  • x/X:删除当前/前一个字符
  • s:删除字符,进入insert模式
  • dd:删除当前行
  • D:normal模式删除当前位置至行尾
  • <c-h>/<m-h>:insert模式backspace

复制、粘贴

  • ["<reg>]y:复制选中区域至寄存器<reg>,默认 "<reg>
  • yy:复制当前行
  • ["<reg>]p:粘贴"<reg>寄存器中内容,默认"<reg>

其他

  • J:合并下一行,<space>分隔
  • u/U(visual):转换为小、大写
  • ~(normal):当前字符大、小写切换(光标移动至下个字符)
  • ~(visual):选中区域大、小写切换
  • gu/gU(normal)区域转换为小、大写
  • g~区域大、小写切换
  • [num]>/<:右/左移动区域num个shiftwidth单位
  • =区域格式化(修改为标准缩进)
  • <c-d>/<c-i>:insert模式减少/增加缩进
  • gc(visual/normal):选中区域按行注释/取消注释 (应该是按vim的filetype确定注释格式)
  • <c-a>/<c-x>:将光标下数字增加/减少1,支持多种进制

功能性

记录

  • q<reg>:宏记录,记录行为于寄存器<reg>中,按下q则 停止记录
  • @<reg>:调用寄存器<reg>中的宏操作(不一定是q<reg> 记录的结果)
  • m<char>:记录当前位置于<char>中(不是寄存器中未知)
  • `\:回到<char>中记录的位置

撤销、redo

  • .:重复上一个操作
  • u:撤销上一个操作
  • <c-r>:继续执行,撤销u
  • <c-m>:等同于<cr>

外部功能

  • K:对当前单词调用keywordprg设置的外部程序,默认“man”

Diff

  • ]c/[c:比较窗口中移至下个不同的为止
  • do/dp:将当前比较窗口中不同区域,同步为/至另一个 窗口该位置

其他

  • q::vim命令历史窗口

界面变动

窗口

Window

  • <c-w-h/j/k/l>:切换至左/下/上/右窗口
  • <c-w-w>:轮换窗口(切换活动窗口)
  • <c-w-t/b/p>:切换至最左上/右下/前个窗口
  • <c-w-+/->:竖直方向扩展/收缩当前窗口
  • <c-w->/<>:水平方向扩展/收缩当前窗口
  • <c-w-=>:恢复当前窗口高度
  • <c-w-H/J/K/L>:移动窗口至tab左/下/上/右,占据全部高/宽
  • <c-w-T>:移动窗口至新tab
  • <c-w-r/x>:交换窗口位置(具体逻辑未知)
  • ZZ:保存退出
  • ZQ:放弃保存退出

Tab

  • [n]gt/gT:下/上一个tab;第n个tab

内容

折叠

  • foldmethod=marker{{{`、`}}}标记折叠区域(各花括号之间无空格)

    • zf:创建折叠(在选中区域前后添加标记)
      • zf[n]G:创建当前行至第n行折叠
      • [n]zf[+]:创建当前行至后n行折叠
      • [n]zf[-]:创建当前行至前n行折叠
    • zd:删除 包含 当前位置折叠
    • zD递归 删除包含当前位置折叠、及子折叠
    • zE:删除窗口中所有折叠
    • za:折叠 toggle
    • zo:折叠展开
    • zc:折叠
  • foldmethod=indent:缩进标记折叠

    • zc:折叠
    • zC递归 折叠
    • zo:展开折叠
    • zO:递归展开折叠
    • [z:移至当前折叠开始
    • ]z:移至当前折叠末尾
    • zj:移至下个折叠开始(包括关闭折叠)
    • zk:移至上个折叠结束(包括开闭折叠)
    • zm:提高折叠水平,即依次折叠当前最高水平缩进
    • zr:降低折叠水平,即依次展开当前最高水平缩进
    • zn:禁用折叠
    • zN:启用折叠
  • foldmethod=manual:手动折叠

    • zf<range>:折叠选中区域
      • zf70j:折叠之后70行
      • zfa(:折叠 ( 包围区域
  • mkview:保存折叠状态

  • loadview:载入折叠状态

Vim Cmd常用命令

内容相关

查找

//?

:/foo向下查找,:?foo向上查找

  • set ingorecase时,不敏感查找;set smartcase时,如果 查找中有大写字符则敏感;
  • :/foo\c手动强制大小写不敏感,:/foo\C强制敏感
  • nN重复同向、反向之前查找
:vimgrep

文件间搜索

1
:vim[grep] /pattern/[g][j] files
  • 选项

    • g:全局匹配(匹配每行全部)
    • j:查找完毕后,进更新quickfix列表,光标不跳转
  • files

    • %:当前文件
    • *:当前目录
    • **/*:仅子目录
    • **/xxxx:当前目录及子目录所有满足xxxx模式文件
    • pattern:满足pattern的文件
global
  • [range]范围(默认整个文件)中查找{pattern},标记 匹配行
  • 对匹配行执行命令{command}(默认print命令)
    • 若标记行在被操作之前已经被删除、移动、合并等而消失, 则不对器执行操作
1
:[range]g[lobal][!]/{pattern}/{command}
  • 选项
    • [!]:对不匹配者执行草在
1
2
3
4
5
6
7
8
9
10
11
12
:g/^/m 0
# 将文件反序
:g/^/+1 d
:%normal jdd
# 删除偶数行
:g/^/d|m.
:%normal jkdd
# 删除奇数行
:g!/aaa/d
# 删除不包含`aaa`行
:g/aaa/"ay
# 复制包含`aaa`行至寄存器`"`

替换

:s
1
:[start,end]s/foo/bar[/i][I][g]
  • 替换区域:默认只替换当前行
    • 手动指定具体行号::2,4s/foo/bar(左闭右开)
    • 特殊符号
      • 全文替换%:%s/foo/bar
      • 第一行^:^,4s/foo/bar
      • 当前行.:.,6s/foo/bar
      • 末尾行$:4,$s/foo/bar
    • visual模式下,手动选择区域命令行自动补全为:'<,'>
  • 替换标志
    • 大小写不敏感/i\c:%s/foo/bar/i:%s/foo\c/bar
    • 大小写敏感/I\C%s/foo/bar/I:%s/foo\C/bar
    • 全局替换/g(替换每行全部模式)::%s/foo/bar/g
      • 默认情况下只替换首个模式:foo,foobar被替换为 bar,foobar
      • 全局替换模式下:foo,foobar被替换为bar,barbar
  • 交互(确认)替换::%s/foo/bar/c,每次替换前会询问
  • 超级变量
    • &:代表被替换模式字串

文本移动

>/<
1
2
:[range]>
:[range]<
  • 范围内文本块右、左移动1个shiftwidth
  • 移动num个shiftwidth添加num个>/<
move
1
:[range]m[ove] [n]
  • 移动范围内行至第[n]
1
2
:m0
# 移动当前行至首行
t
1
:[range]t [n]
  • 复制范围内至第[n]
1
2
:t.
# 复制当前行至下行

文件相关

放弃修改、重新加载、保存

  • :w[rite]:保存此次修改
  • :e!:放弃本次修改(和:q!不同在于不会退出vim)
  • :bufdo e!:放弃vim所有已打开文件修改
  • :e:重新加载文件
  • :e#:当前窗口加上个buffer(反复切换)
  • :bufdo e:重新加载vim所有已打开文件
  • :saveas new_file_name:另存为,不删除原文件
  • :sb[n]:split窗口加载第n个buffer
  • :b[n]:当前窗口加载第n个buffer
  • :n[n]:当前窗口加载下/第n个buffer

Window

  • :sp[lit]:水平分割当前窗口,展示当前文件
  • :vs[plit]:竖直分割当前窗口,展示当前文件
  • :new:水平分割当前窗口,新文件
  • :vnew:竖直分割当前窗口,新文件
  • :sview:水平分割当前窗口,只读[缺省当前]文件
  • :[n]winc >/<:水平方侧扩展/收缩
  • :[n]winc +/-:竖直方向扩展/收缩
  • :res+/-[n]:竖直方向扩展/收缩
  • :vertical res+/-[n]:水平方向扩展/收缩
  • :ressize[n]:高度设置为n单位
  • :vertical res[n]:宽度设置为n单位
  • :q[uit][!]:退出当前窗口
    • !:强制退出,修改不保存
  • :close:关闭当前窗口(不能关闭最后窗口)
  • :only:关闭其他窗口
  • :qa:退出所有窗口
  • :wq:保存、退出当前窗口
  • :x:类似于wq,但是未修改则不写入

注:

  • 水平方向:扩张优先左侧变化,收缩右侧变化
  • 竖直方向:扩展收缩均优先下侧变化

Tab

  • :tabnew [opt] [cmd] [file_name]:打开新tab
  • :tabc:关闭当前tab
  • :tabo:关闭其他tab
  • :tabs:vim cmd区域查看所有打开的tab信息
  • :tabp:查看前一个tab
  • :tabfirst/:tablast:第一个/最后一个tab
  • :tabn [num]:查看下一个/第num个tab

Diff

  • :diffsplit [filename]:上下分割窗口和当前窗口比较

    • 默认同当前文件进行diff
  • :difft:将当前窗口变为比较窗口

    • 若没有其他比较窗口,则没有明显变化
    • 若存在其他比较窗口,则加入比较
  • :diffu[pdate][!]:更新当前比较窗口

    • 比较状态下修改当前文件后,重新生成比较信息
    • !:重新载入文件后更新(外部修改文件)
  • :diffo[!]:关闭当前窗口比较状态

    • !:关闭所有窗口比较状态

Session

  • :mksession[!] <session-file-name>:将当前状态写入 session 文件
  • :source <session-file-name>:载入已有 session 文件

其他

多行语句

“|”管道符可以用于隔开多个命令:echom "bar" | echom "foo"

:vertical

:vertical基本可以用所和窗口有关命令之前,表示左右(分割)

  • :vert split/:vs:左右分割窗口
  • :vert sb[n]:左右分割窗口载入buff[n]
  • :vert diffs file_name:左右分割窗口diffs
  • :vert res +/-[n]:调整窗口大小

其他CMD命令

编辑过程中使用shell

  • :!{shell command}即可直接执行shell命令并暂时跳出vim

    • :r !{shell command}可以将输出结果读取到当前编辑
    • :w !{sheel command}可以将输出结果输出到vim命令行
  • :shell即可暂时进入到shell环境中,$exit即可回到vim中

  • <c-z>暂时后台挂起vim回到shell环境中,$fg即可回到之前 挂起的进程(此时为vim,详见fg命令)

读取结果

  • :read cmd:读取cmd结果至光标下一行
    • :read !date:读取系统date命令结果

交换文件处理

  • 确认需要恢复:直接恢复R

  • 确认丢弃:直接删除D

  • 没有明确目标:只读打开O

  • 比较交换文件、现在文件差别

    • 恢复打开R
    • 另存为其他文件:saveas filname.bak
    • 与当前文件对比:diffsplit filename
  • 一般不会直接Eedit anyway

Vim命令行参数

vim

  • $ vim [filname]:打开一般窗口
    • -r [filename]:常看交换文件(特定文件对应交换文件)
    • -R [filename]:只读方式打开文件
    • -S session-file:打开session的方式启动vim
      • 需要 :mksession[!] <session-file> 先创建 session 文件

vimdiff

  • $ vimdiff [file1] [file2]:打开比较窗口
    • -u:合并模式比较
    • -c:上下文模式比较
  • 后面两个模型可常用于输出重定向至新文件

Shell执行控制

符号

命令执行

  • ;:连续执行指令,分割多条命令

    • 所以如果不是在一行内执行,;是可以有任意多个
  • ::内建空指令,返回值为0

  • &&, ||:逻辑与、或,全部(任意)之前的命令执行成功才会 执行下连接中的命令

“转义”

  • \\:转义字符

    • 放在指令前,取消alias
    • 特殊符号前转义,Shell将不对其后字符作特殊处理,当作 普通字符(即$, \', \"
    • 行尾表示连接下一行,回车符只起换行作用,视为空格
  • $:变量符号,表示其后字符串为一个变量

  • \', \":内部视为字符串

  • --:命令行中转义-,否则shell认为-是参数选项

    1
    2
    $ rm -- -file
    # 删除文件`-file`
    • 还可以在之前加上路径避免-被解释为参数选项
    • \''等均无效

引号

单引号''

  • 单引号括起字符都作为普通字符,变量无效

  • 单引号字串中不能出现单独的单引号,使用转义符也不行,但是 可以成对出现,作为字符串拼接使用

双引号""

  • 双引号字串中可以有变量、转义字符

反引号``

反引号扩起字符串表示Shell解释命令,执行时shell首先解释其, 以标准输出替代整个反引号

  • 括号中语句为命令,分号连接

    • ``中的表达式只需要符合C语言的运算规则 即可,甚至可以使用三目预算符、逻辑表达式
  • 命令和括号之间无空格

  • $``可以将命令输出作为变量返回值,同$()

括号

()

  • 命令组/运算表达式:其中的命令列表将在新子shell运行

    • 其中变量之后不能使用,不影响当前shell环境
    • 多个命令之间分号分隔,最后命令可以省略
    • 命令和括号之间可以无空格
  • 命令替换:等同于引号``

    • bash扫描命令行,执行$()结构中命令,将标准输出作为 匿名变量值
    • ()中出现()不需要转义,``需要转义
    • ()中不能使用C风格的运算表达式
    • 部分shell可能不支持(),如:tcsh
  • 初始化数组:参见数组

(())

  • 整数扩展:计算、扩展算数表达式结果

    • 表达式结果为0则退出状态为1、false
    • 表达式结果为1则退出状态为0、true
    1
    2
    a=5;((a++))			# 自增运算符
    b=$((16#5f)) # 进制转换
    • 退出状态和[]完全相反
    • 其中可使用任何符合C语言的运算,包括三目运算符
  • 算术比较:

    • 其中变量可以不使用$前缀、支持多个表达式逗号分隔
    • 可直接使用C风格表达式,如:forwhile循环语句中
1
2
3
4
5
6
7
for((i=0;i<5;i++))
for i in `seq 0 4`
for i iin {0..4}
# 三者等价
if ((i<5))
if [ $i -lt 5 ]
# 二者等价

[][[]]

  • []

    • 条件测试表达式:参见if
    • 数组索引
    • 正则表达式范围
  • [[]]

    • 条件测试表达式:参见if

{}

  • 创建匿名函数

    • 不开启新进程
    • 括号内变量之后可继续使用
    • 括号内命令分号分隔,最后一个语句也要有分号
    • {和第一个语句之间要有空格
  • 字符串

    • 默认值替换:参见字符串默认值替换
    • 获取子串:参见字符串子串
    • 获取切片:参见字符串子串
    • 字符串替换:参见字符串子串
  • $后包括变量名精确分隔变量名,参见变量使用

其他符号

!

Shell中!称为事件提示符,可以方便的引用历史命令:当! 后跟随字母不是空格、换行、回车、=(时,做命令替换

  • ![-]n:引用history中的正数/倒数第n个命令

    • !!:等同!-1,执行上条命令
  • !cmd:引用最近以cmd开头的命令,包括参数

    • !cmd:gs/pattern/replace:将上条cmd开头命令中 pattern替换为replace
  • !?str[?]:引用最近包含str的命令,str可以是参数

  • 参数引用

    • !$:最后一个参数
    • !:-:除最后一个参数
    • !*:所有参数

控制语句

if[]

用于条件控制结构,结构如下

1
2
3
4
if test_expression; then
then command_1
else command_2
fi
  • test <expr>:bash内部命令,判断表达式是否为真

    • 其后只能有一个表达式判断,无法使用逻辑与、或连接
  • [ <expr> ]:基本等同于test

    • 整数比较:-ne-eq-gt-lt
    • 字符串比较:转义形式大、小号\</>
    • 逻辑表达式连接:-o(或)、-a(与)、!(非) (不能使用||(或)、&&(与))
    1
    2
    3
    if [ $? == 0 ]
    if test $? == 0
    # 二者等价
    • 注意内部两边要有空格
    • 事实上是[等同于test]表示关闭条件判断,新版 bash强制要求闭合
  • [[ <expr> ]]条件测试

    • 整数比较:!==<>
    • 字符串:支持模式匹配(此时右侧模式时不能加引号)
    • 逻辑表示式连接:||(或)、&&(与)、!(非)
    1
    2
    3
    4
    if [[ $a != 0 && $b == 1 ]]
    if [ $a -eq 0 ] && [ $b -eq 1]
    if [ $a -eq 0 -a $b -eq 1]
    # 三者等价
    • [[:bash关键字,bash将其视为单独元素并返回退出 状态码

case

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
case chars in
char_pattern_1)
# `)`是必要的
# 匹配即停止,不会下沉
command_1
;;
# 每个模式字符串可以有多条命令,最后一条必须以`;;`结尾
char_pattern_2 | char_pattern_3)
# `|`分隔,或,可以匹配其中一个模式即可
command_2
;;
*)
# 匹配所有字符串模式,捕获所有
command_3
;;
esac
# 返回值位最后执行命令的退出值,未执行命令则为0

while

1
2
3
4
5
6
while test_expression
# test_expression是指`test`、`[]`语句
# 测试条件为真进入循环体
do
command_1
done

until

1
2
3
4
5
until test_exprssion
# 测试条件为假进入循环体
do
command_1
done

for

CStyle

1
2
3
4
5
for ((i=0; i<limit; i++))
# C-style for
do
command_1
done

ListStyle

1
2
3
4
5
for var in var_arr
# list-style for
do
command
done
FileIterator
1
2
3
4
5
6
for var in /path/to/file_regex
# `var`依次取(当前)目录下的与正则表达式匹配的文件名
# 执行循环体语句
do
command
done
  • /path/to/file_regex注意
    • 路径不存在:$var为该字符串
    • 不能用""括起,否则:$var只取路径下所有匹配合并 ,空格分隔
ParamsIterator
1
2
3
4
5
6
for var[ in $*]
# `var`依次取位置参数的值,执行循环体中命令
# `[ in $*]`可以省略
do
command
done
RangeIterator
1
2
3
4
5
6
7
8
9
for i in $(seq start end)
do
command
done

for i in {start..end}
do
command
done

break, continue, exit

  • break[n]:跳出n层循环体,默认跳出一层循环体
  • continue[n]:跳过n层循环体在其之后的语句,回到循环开头 ,默认跳过一次循环体
  • exit:退出程序,后跟返回值

Bash 编程技巧

检查命令是否成功

  • 原版

    1
    2
    3
    4
    5
    6
    7
    echo abcdee | grep -q abcd

    if [ $? -eq 0 ]; then
    echo "found
    else
    echo "not found"
    fi
  • 简洁版

    1
    2
    3
    4
    5
    if echo abcdee | grep -q abc; then
    echo "found"
    else
    echo "not found"
    fi
  • 精简版

    1
    echo abcdee | grep -q abc && echo "found" || echo "not found"

标准输出、错误输出重定向到/dev/null

  • 原版

    1
    $ grep "abc" text.txt 1>/dev/null 2>&1
  • 简洁版

    1
    $ grep "abc" text.txt &> /dev/null

awk使用

  • 原版
    1
    $ sudo xm li | grep vm_name | awk `{print $2}`
  • 简洁版
    1
    $ sudo xm li | awk `/vm_name/{print $2}`

逗号连接所有行

  • 原版:sed

    1
    $ sed ":a;$!N;s/\n/,;ta" test.txt
  • 简洁:paste

    1
    $ paste -sd, /tmp/test.txt

过滤重复行

  • 原版:sort

    1
    $ sort text.txt | unique
  • 简洁版

    1
    $ sort -u text.txt

Bash 脚本执行

脚本执行

#!

脚本首行注释

  • 文件执行时,shell会将文件内容发送至#!之后的解释器上
  • 不限于shell脚本,也适合其他类型的脚本语言
    • 当然要求#为脚本语言支持的注释符
  • 建议在首行使用env命令而不是硬编码解释器路径,这样可以 减少对机器的依赖
    1
    2
    #!/usr/bin/env python
    #!/usr/bin/env shell

4种执行方式

  • $ file_name:表示在当前shell执行文件,需要有文件的执行 权限

  • $ source/. file_namesource.意义一致,表示读取 文件内容在shell中,然后在shell里执行文件内容,需要读权限

  • $ sh file_name:表示开启一个新的shell进程,并读取文件 内容在新的shell中然后执行,同样的需读权限

以下面的文件test.sh为例

1
2
3
4
5
#!/bin/bash
echo "fisrt"
sleep 1000
echo "second"
slepp 1000
  • $ test.sh:产生两个新进程test.sh和sleep,在second输出 之前<ctrl-c>,会同时终止两个进程,不会继续输出second

  • $ sh test.sh:产生两个新进程,shell和sleep,在second 输出之前<ctrl-c>,同样的会同时终止两个进程,不会继续 输出second(实际上first是在新的shell里输出的)

  • source/. test.sh:产生一个新进程sleep,在second输出之前 <ctrl-c>,只有sleep进程被终止,而test.sh的内容在当前 shell里直接执行,当前shell没有被终止,second会继续输出

结论

  • 如果需要对当前shell进行设置,应该使用source/.

  • 否则这三种执行方式除了进程产生、权限要求应该没有差别

Shell环境

环境变量

  • 设置环境变量直接:$ ENV_NAME=value=前后不能有空格) 但是此时环境变量只能在当前shell中使用,需要export命令 导出之后才可在子shell中使用

  • 环境变量设置代理

    1
    2
    export http_proxy=socks://ip
    export https_proxy=socks5://ip

输入输出

  • 0:STDIN_FILENO,标准输入
  • 1:STDOUT_FILENO,标准输出
  • 2:STDERR_FILENO,标准错误

说明:

  • 标准输出和标准错误虽然都是在命令行上显示,但是两个是 不同的流。输出重定向>只能将标准输出重定向,不会将 标准错误重定向,其仍然会在命令行显示

重定向

  • <:重定向标准输入
  • >:标准输出write重定向
  • >>:标准输出add重定向
  • 2>:标准错误重定向

说明:

  • 输出重定向就是1 > outputcommand > output只是省略 1的简写

    • 命名自己不是输出,不能重定向
    • 是命令产生的标准输出重定向
  • 可以通过2>&1将标准错误重定向到标准输出,从而将命令的 标准输出、错误输出同时输出

    • &这里表示等效于标准输出(标准输出的引用)
    • command>a 2>acommand>a 2>&1看起来类似,实际上 前者写法会打开两次a,stderr覆盖stdout,而后者是 引用,不会覆盖、IO效率更高
    • 2>&1放在后面大概是因为需要获取stdout的引用,所以 需要标准输出先给出重定向
    • 这种写法还有个简写&>>&
  • 可以重定向到设备,在*nix系统中,设备也被视为文件

    1
    $ echo "hello" > /dev/tty01

    特别的设备/dev/null可以作为不需要输出的重定向目标

HereDoc Format

HereDoc Format:特殊的重定向,指示shell从标准输入读取输入 直至遇到标记行(前后不能有空白符)

1
2
3
<CMD> << <EOF>
here-doc
<EOF>
  • EOF:标记字符串,常用EOFSTOP
  • 若标记中含有字符被quote(如被引号包括)

    • 结束标记为去除quotation结果
    • here-doc中不执行参数扩展、命令替换、算数扩展
  • 若标记中没有quotation

    • here-doc中执行参数扩展、命令替换、算数扩展
    • 此时\$、反引号需要\转义

管道

|:将一个程序的标准输出发送到另一个程序的标准输入

  • 一些平台会并行启动以管道连接的程序,此时使用类似迭代器 输出、输入能提高效率

Shell内置命令

  • which命令无法找到的命令

set

set:设置所使用的shell选项、列出shell变量

  • :不带参数,显示全部shell变量
  • -a:输出之后所有至export(环境变量)
  • -b:使被终止后台程序立即汇报执行状态
  • -B:执行括号扩展
  • -C:重定向所产生的文件无法覆盖已存在文件
  • -d:shell默认使用hash表记忆已使用过的命令以加速 执行,此设置取消该行为
  • -e:若指令回传值不为0,立即退出shell
  • -f:取消使用通配符
  • -h:寻找命令时记录其位置???
  • -H:(默认)允许使用!<编号>方式执行history中 记录的命令
  • -k:命令=被视为设置命令的环境变量
  • -m:监视器模式,启动任务控制
    • 后台进程已单独进程组运行
    • 每次完成任务时显示包含退出的状态行
  • -n:读取命令但不执行
    • 通常用于检查脚本句法错误
  • -p:允许set-user/group-id
    • 禁止处理$ENV文件、从文件中继承shell函数
  • -P:处理cd等改变当前目录的命令时,不解析符号链接
  • -t:读取、执行下条命令后退出
  • -u:使用未设置变量作为错误处理
  • -v:输入行被读取时,显示shell输出行
  • -x:显示简单命令的PS4扩展值(包括所有参数)、当前命令 的环境变量
  • -o:option-name,下列之一
    • allexport:同-a
    • braceexpand shell:(默认)执行花括号扩展
    • emacs:(默认)使用emacs风格命令行编辑接口
    • errexit:同-e
    • errtrace:同-E
    • functrace:同-T
    • hashall:同-h
    • histexpand:同-H
    • history:记录命令历史
    • ignoreeof:读取EOF时不退出shell
    • interactive-comments:允许交互式命令中出现注释
    • keyword:同-k
    • monitor:同-m
    • noclobber:同-C
    • noexec:同-n
    • noglob:同-f
    • noglob:currently accepted but ignored
    • nohash:同-d
    • notify:同-b
    • nounset:同-u
    • physical:同-P
    • pipfail:管道命令返回值为最后返回值非0命令的状态, 若没有非0返回值返回0
    • posix:改变shell属性以匹配标准,默认操作不同于 POSIX1003.2标准
    • priviledged:同-p
    • verbose:同-v
    • vi:使用vi风格的命令编辑接口
    • xtrace:同-x
  • +:加以上参数取消标志位设置(包括o参数)
  • --:给所有剩余参数设置标志位,没有剩余参数则unset
  • -:给所有剩余参数设置标志位
  • $-中存放有当前已设置标志位

let

let:执行计算的工具,用于执行一个、多个表达式

  • 变量计算中不需要$标识变量
  • 表达式中包含特殊字符,需要引起来

declare

declare:声明变量内容

  • -a:声明变量为普通数组
  • -A:声明变量为关联数组(下标支持字符串,类似字典)
  • -i:声明变量为整形
  • -r:声明变量只读
  • -x:设置为环境变量(export
  • -g:在函数中创建全局变量
  • +:和以上联合使用,取消定义的变量类型

  • -f:列出脚本中定义的函数名称、函数体

  • -F:列出脚本中定义的函数名称
  • -p:查看变量属性、值

read

read:从标准输入读入变量内容

1
2
$ read [<option>] <var>[ <var2>...]
$ read -p "Enter names: " name1, nem
  • 读取值数目大于变量数目时,多余值均赋给最后变量
  • -p:命令行提示内容
  • -n:不换行
  • -d:分隔标记
  • -t:阻塞等待时常,之后返回非零
  • -s:隐藏输入
  • -r:反折号不被视为转义标记
1
2
3
cat README | while read -r line; do
echo $line
done

shift

shift:移除参数列表中头部部分参数,缺省移除1个

  • shift移除从$1开始,无法移除$0

getopts

getopts:逐个读取解析单字符指示的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function func (){
echo OPTIND: $OPTIND
while getopts ":a:B:cdef" opt; do
case $opt in
a) echo "this is -a the arg is ! $OPTARG at $OPTIND" ;;
B) echo "this is -B the arg is ! $OPTARG at $OPTIND" ;;
c) echo "this is -c the arg is ! $OPTARG at $OPTIND" ;;
\?) echo "Invalid option: -$OPTARG" ;;
esac
done
echo OPTIND: $OPTIND
echo $@
shift $(($OPTIND - 1))
echo $@

}
func -a 23 -B 1904-03-04 343 age
  • $OPTARG:参数值
  • $OPTIND:在参数列表中位移,初始值为1,常配合shift 使用剔除已处理参数
  • 遇到未指定option则返回0
  • option字符后::字符可以带有参数,赋给$OPTARG;否则 仅表示标志,仅该字符被处理

  • option_string开头:可以避免错误输出

    • :标记option不带参数时
      • 待匹配值设为:
      • $OPTARG设为option
    • option无效时
      • 待匹配值设为?
      • $OPTARG设为option
  • 函数内部处理函数参数,否则处理脚本参数
  • 参数标识-可省略

Linux介绍

Linux版本

内核版本

内核版本号由3个数字组成X.Y.Z-P

  • X:主版本号,比较稳定,短时间不会改变
  • Y:次版本号,表示版本类型
    • 偶数:稳定版
    • 奇数:测试版
  • Z:发布号,数字越大,功能越完善
  • P:patch号

Linux分区

/boot引导分区目录

该分区(目录)存放系统内核、驱动模块引导程序,需要独立 分区

  • 避免(根)文件系统损坏造成无法启动
  • 避使用lilo引导时1024柱面问题(Grub无此问题)
  • 方便管理多系统引导

/boot修复

进入grub模式后#todo

/swap分区目录

系统物理内存不足时,释放部分空间,其中数据被临时保存在 swap空间中

  • 不是所有物理内存中交换的数据都会被放在交换空间中,有部分 数据直接交换到文件系统

  • 交换空间比内存慢

  • 安装时,系统会尝试将交换分区安装到磁盘外端

  • 有多个磁盘控制器时,在每个磁盘上都建立交换空间

  • 尽量将交换空间安装在访问在频繁的数据区附近

  • 交换空间大小一般设置为内存1-2倍

  • 不推荐为交换空间划分单独分区,可以使用交换文件作为交换 空间,方便、容易扩展
交换文件
1
2
3
4
5
6
7
8
9
10
11
12
13
$ dd if=/dev/zero of=/swapfile bs=1024 count=32000
#
$ fallocate -l 32G /swapfile
# 创建有连续空间的交换文件,大小为1024*32000=32G
$ chmod 600 /swapfile
# 修改交换文件权限
$ mkswap /swapfile
# 设置交换文件

$ /usr/sbin/swapon /swapfile
# 激活上步创建的`/swapfile`交换文件
$ /usr/sbin/swapoff swapfile
# 关闭交换文件
  • 不需要交换文件时可以直接rm删除
  • 可以在fstab文件中添加交换文件,自动挂载,格式参见 config_files

/根分区目录

  • /usr:用户程序
  • /sbin:系统管理员执行程序
  • /bin:基本命令
  • /lib:基本共享库、核心模块
  • /home:用户目录
  • /etc:配置文件目录
  • /opt:附加应用程序包目录
  • /mnt:设备/文件系统挂载目录
  • /dev:设备
  • /tmp:临时文件
  • /var:可变信息区
    • file spool
    • logs
    • requests
    • mail
  • /proc:进程(映射)信息

Terminal、CLI、Shell、TTY

Terminal

  • Termianl 终端:计算机领域的终端是指用于 与计算机进行交互的输入输出设备,本身不提供运算处理功能

    • 大部分情况下,终端将用户的字符以外键盘输入转为控制序列
    • 但接收到 <C-C> 等特殊组合键时,发送特殊信号
  • Console 控制台:和计算机一体的特殊终端,用于管理主机,比普通终端权限更高

    • 一台主机一般只有一个控制台,但可以连接多个普通终端
    • Console、Terminal随着PC普及已经基本时同义词

TTY

  • TTY:原含义即为直电传打字机 TeletypePrinterTeletypeWriter:键盘输入指令、纸带打印信号

    • UNIX 为支持电传打字机设计了名为 tty 的子系统
    • 之后 tty 名称被保留成为终端的统称(虽然终端设备不局限于 tty
  • UNIX 系统中

    • 具体终端硬件设备抽象为操作系统内部 /dev/tty* 设备文件
    • /dev/tty[1-6] 即对应 6 个虚拟控制台
  • 另外,早期计算机上 Serial Port 最大用途就是连接终端设备

    • 所以会把行端口上设备同样抽象为 tty 设备
    • /dev/ttyS* 对应串口设备
  • Linux TTY/PTS概述
  • Linux 系统中,<C-A—[F1-F6]> 可以切换终端
  • 可通过 $ stty -a 查看当前终端设置

分类

  • Character/Text Terminal:字符终端,只能接受、显示文本信息的终端

    • Dumb Terminal:哑终端
    • Intelligent Terminal:智能终端,相较于哑终端
      • 理解转义序列
      • 定位光标、显示位置
  • Graphical Terminal:图形终端,可以显示图形、图像

    • 现在专门图形终端已经少见,基本被 全功能显示器 取代

Terminal Emulator

终端模拟器:默认传统终端行为的程序,用于与传统的、不兼容图形接口命令行程序(如:GNU 工具集)交互

  • CLI 程序,终端模拟器假装为传统终端设备
  • 对现代图形接口,终端模拟器假装为 GUI 程序
    • 捕获键盘输入
    • 将输入发送给 CLI 程序(bash
    • 得到命令行程序输出结果
    • 调用图形接口(如:X11),将输出结果渲染至显示器
  • tty[1-6] 也是终端模拟器,只是不运行在图形界面中、由内核直接提供,也称虚拟控制台

ShellTerminal

  • Shell 更多指提供和内核交互入口的软件,提供

    • 命令提示符 Prompt
    • 行编辑、输入历史、自动补全(但是也有些终端自己实现 此功能)
  • Terminal 更多指 IO 端口硬件,提供

    • 上、下翻页查看内容
    • 终端中复制、粘贴功能

Shell

pc_architecture

Shell:提供 用户界面 的程序,接受用户输入命令和内核沟通

  • Shell 向用户提供操作系统入口

    • 避免普通用户随意操作导致系统崩溃
    • 虽然Shell会调用其他应用程序,其他应用程序再调用系统调用,而不是直接与内核交互
  • Command-Line Interface:命令行 Shell,通常不支持鼠标,通过键盘输入指令

    • shBourne Shell
    • bashBourne-Again Shell
    • zhsZ Shell
    • fishFriendly Interactive Shell
    • cmd.exe:这个应该看作是 Shell,而不是 Terminal
      • 可与内核进行交互
      • 接受键盘输入是其宿主的功能(即宿主作为隐式 Terminal Emulator
    • PowerShell
  • GUIGraphic User Interface 图形 Shell

    • Windows 下的 explorer.exe

Linux 系统启动

登陆、退出、关机、重启

login

登陆系统

logout

退出shell

exit

退出shell(常用)

rlogin

远程登陆服务器

poweroff

关闭系统,并将关闭记录写入/var/log/wtmp日志文件

ctrlaltdel

强制或安全重启服务器

shutdown

关闭系统

halt

关闭系统

reboot

重启系统

init 0/6

关机/重启

Shell 环境变量

环境

export

显示、设置环境变量,使其可在shell子系统中使用

  • 设置环境变量直接$ ENV=value即可,但是此环境变量 不能在子shell中使用,只有$ export ENV导出后才可
  • -f:变量名称为函数名称
  • -n:取消导出变量,原shell仍可用
  • -p:列出所有shell赋予的环境变量

系统环境变量

NAME

  • PATH:用户命令查找目录
  • HOME:用户主工作目录
  • SHELL:用户使用shell
  • LOGNAME:用户登录名
  • LANG/LANGUAGE:语言设置
  • MAIL:用户邮件存储目录
  • PS1:命令基本提示符
  • PS2:命令附属提示符
  • HISTSIZE:保存历史命令记录条数
  • HOSTNAME:主机名称
  • /etc/passwd/etc/hostname等文件中设置各用户部分 默认值,缺省随系统改变

PATH

C PATH

  • LIBRARY_PATH:程序编译时,动态链接库查找路径
  • LD_LIBRARAY_PATH:程序加载/运行时,动态链接库查找路径
  • 动态链接库寻找由/lib/ld.so实现,缺省包含/usr/lib/usr/lib64
    • 建议使用/etc/ld.so.conf配置替代LD_LIBRARY_PATH, 或在编译时使用-R<path>指定
    • 手动添加动态链接库至/lib/usr/lib等中时,可能 需要调用ldconfig生成cache,否则无法找到

Shell 常用工具

获取命令系统帮助

help

重看内部shell命令帮助信息(常用)

man

显示在线帮助手册(常用)

info

info格式的帮助文档

打印、日期、时间

echo

输出至标准输出

env

打印当前所有环境变量

cal

显示日历信息

date

date:显示、设置系统日期时间

1
date -d <time> "+<format>"
  • -d:指定时间,缺省今天
  • +:指定输出格式
    • %Y-%m-%d %h-%M-%S:年月日时(24时)分秒
    • %a/%A:星期缩写、完整
    • %b/%B:月份缩写、完整
    • %DMM/DD/YY
    • %FYYYY-MM-DD

hwclock

查看、设置硬件时钟

clockdiff

主机直接测量时钟差

rdate

通过网络获取时间

sleep

暂停指定时间

数值计算

bc

任意精度计算器

expr

将表达式值打印到标准输出,注意转义

Shell 本地化

本地化

字体

fc-

  • fc-list:列出系统已安装字体

    1
    2
    # 仅展示中文字体
    $ fc-list :lang=zh
  • fc-cache:创建字体信息缓存文件

  • mkfontdir/mkfontscale:创建字体文件索引

  • 字体安装

    • 将字体文件复制至字体文件夹
      • $HOME/.fonts
      • /usr/share/fonts
    • fc-cache 更新缓存信息