Linux Shell及vi/vim使用

Linux Shell及vi/vim使用

vi/vim 简单使用

概念

vi是unix下的编辑程序,vim由vi改编增强版。

现在一般用的是vim

vim有多种模式

  • 普通模式(Normal mode)

在普通模式中,用的编辑器命令,比如移动光标,删除文本等等。这也是 Vim 启动后的默认模式。这正好和许多新用户期待的操作方式相反(大多数编辑器默认模式为插入模式)。

这种设置与其他文本编辑器不太一样,但这样的话可以更快移动光标

在普通模式中,有很多方法可以进入插入模式。比较普通的方式是按 a(append/追加)键或者 i(insert/插入)键。

  • 插入模式(Insert mode)

在这个模式中,大多数按键都会向文本缓冲中插入文本。大多数新用户希望文本编辑器编辑过程中一直保持这个模式。

在插入模式中,可以按 ESC 键回到普通模式。

  • 可视模式(Visual mode)

这个模式与普通模式比较相似。但是移动命令会扩大高亮的文本区域。高亮区域可以是字符、行或者是一块文本。当执行一个非移动命令时,命令会被执行到这块高亮的区域上。Vim 的”文本对象”也能和移动命令一样用在这个模式中。

  • 选择模式(Select mode)

这个模式和无模式编辑器的行为比较相似(Windows 标准文本控件的方式)。这个模式中,可以用鼠标或者光标键高亮选择文本,不过输入任何字符的话,Vim 会用这个字符替换选择的高亮文本块,并且自动进入插入模式。

  • 命令行模式(Command line mode)

在命令行模式中可以输入会被解释成并执行的文本。例如执行命令(:键),搜索(/?键)或者过滤命令(!键)。在命令执行之后,Vim 返回到命令行模式之前的模式,通常是普通模式。

  • Ex 模式(Ex mode)

这和命令行模式比较相似,在使用 :visual 命令离开 Ex 模式前,可以一次执行多条命令。

模式切换

普通模式中按 i(插入)或 a(附加)键都可以进入插入模式,普通模式中按 : 进入命令行模式。命令行模式中输入 wq 回车后保存并退出 vim。

进入vim界面

1
vim practice_1.txt

进入命令行模式后还可以使用 e:file 打开其他文件

游标移动

按键说明
h
l右(小写 L)
j
k
w移动到下一个单词
b移动到上一个单词
0光标到行首
$光标到行末
numG移动到num行
G移动到最后一行
numj向下移动num行
numgg跳转至num行

进入插入模式

按键说明
h
l右(小写 L)
j
k
w移动到下一个单词
b移动到上一个单词

命令行模式下保存文档

从普通模式输入 : 进入命令行模式,输入 w 回车,保存文档。输入 :w <filename> 可以将文档另存为其他文件名或存到其它路径下。

命令行模式下退出 vim

从普通模式输入 : 进入命令行模式,输入 wq 回车,保存并退出编辑。

以下为其它几种退出方式:

命令说明
:q!强制退出,不保存
:q退出
:wq!强制保存并退出
:w <文件路径>另存为
:saveas 文件路径另存为
:x保存并退出
:wq保存并退出

普通模式下退出 vim

普通模式下按下 Shift+zz 即可保存退出 vim。

普通模式下删除 vim 文本信息

进入普通模式,使用下列命令可以进行文本快速删除:

命令说明
x删除游标所在的字符
X删除游标所在前一个字符
Deletex
dd删除整行
dw删除一个单词(不适用中文)
d$D删除至行尾
d^删除至行首
dG删除到文档结尾处
d1G删至文档首部
2dd一次删除两行

行间跳转

命令说明
nG(n Shift+g) / ngg游标移动到第 n 行 (如果默认没有显示行号,请先进入命令模式,输入 :set nu 以显示行号)
gg游标移动到到第一行
G(Shift+g)到最后一行

Ctrl+o 快速回到上一次(跳转前)光标所在位置

行内跳转

普通模式下使用下列命令在行内按照单词为单位进行跳转:

命令说明
w到下一个单词的开头
e到当前单词的结尾
b到前一个单词的开头
ge到前一个单词的结尾
0^到行头
$到行尾
f<字母>向后搜索<字母>并跳转到第一个匹配的位置(非常实用)
F<字母>向前搜索<字母>并跳转到第一个匹配的位置
t<字母>向后搜索<字母>并跳转到第一个匹配位置之前的一个字母(不常用)
T<字母>向前搜索<字母>并跳转到第一个匹配位置之后的一个字母(不常用)

复制及粘贴文本

  • 普通模式中使用 y 复制

  • 普通模式中,yy 复制游标所在的整行(3yy 表示复制 3 行)

  • 普通模式中,y^ 复制至行首,或 y0。不含光标所在处字符。

  • 普通模式中,y$ 复制至行尾。含光标所在处字符。

  • 普通模式中,yw 复制一个单词。

  • 普通模式中,y2w 复制两个单词。

  • 普通模式中,yG 复制至文本末。

  • 普通模式中,y1G 复制至文本开头。

  • 普通模式中使用 p 粘贴

  • 普通模式中,p(小写)代表粘贴至光标后(下)

  • 普通模式中,P(大写)代表粘贴至光标前(上)

    粘贴

  • 普通模式中使用 p 粘贴

  • 普通模式中,p(小写)代表粘贴至光标后(下)

  • 普通模式中,P(大写)代表粘贴至光标前(上)

剪切

dd命令就是剪切

ddp可以实现交换行

字符串替换

命令说明
r+<待替换字母>将游标所在字母替换为指定字母
R连续替换,直到按下 Esc
cc替换整行,即删除游标所在行,并进入插入模式
cw替换一个单词,即删除一个单词,并进入插入模式
C(大写)替换游标以后至行末
~反转游标所在字母大小写
{n}u撤销一次或 n 次操作
U(大写)撤销当前行的所有修改
Ctrl+rredo,即撤销 undo 的操作

快速缩进

  • 普通模式下输入 >> 整行将向右缩进
  • 普通模式下输入 << 整行向左回退
  • 普通模式下输入 : 进入命令行模式下对 shiftwidth 值进行设置可以控制缩进和回退的字符数

:set shiftwidth=10

调整文本位置

:ce

:ri

:le

分别将本行文本靠某个位置

快速查找

普通模式下输入 / 然后键入需要查找的字符串,按回车后就会进行查找。?/功能相同,只不过 ? 是向上而 / 是向下查找。

进入查找之后,输入 nN 可以继续查找。n 是查找下一个内容,N 查找上一个内容。

  • 命令行模式下输入 noh 然后回车即可取消搜索

使用 vim 编辑多个文件

编辑多个文件有两种形式,一种是在进入 vim 前使用的参数就是多个文件。另一种就是进入 vim 后再编辑其他的文件。 同时创建两个新文件并编辑

1
2
3
vim 1.txt 2.txt

默认进入1.txt文件的编辑界面命令行模式下输入 :n 编辑 2.txt 文件,可以加 ! 即 :n! 强制切换,之前一个文件的输入没有保存,仅仅切换到另一个文件命令行模式下输入 :N 编辑 1.txt 文件,可以加 ! 即 :N! 强制切换,之前文件内的输入没有保存,仅仅是切换到另一个文件
  • 命令行模式下输入:e 3.txt 打开新文件 3.txt
  • 命令行模式下输入:e# 回到前一个文件
  • 命令行模式下输入:ls可以列出以前编辑过的文档
  • 命令行模式下输入:b 2.txt(或者编号)可以直接进入文件 2.txt 编辑
  • 命令行模式下输入:bd 2.txt(或者编号)可以删除以前编辑过的列表中的文件项目
  • 命令行模式下输入:e! 4.txt,新打开文件 4.txt,放弃正在编辑的文件
  • 命令行模式下输入:f 显示正在编辑的文件名
  • 命令行模式下输入:f new.txt,改变正在编辑的文件名字为 new.txt

恢复文件

如果因为断电,终端意外关闭等原因造成文档没有保存,可以采用恢复方式。

vim 在编辑的时候会自动在当前文件目录下生成一个交换文件,一般以 <filename>.swp 的格式保存,如果有多个版本的交换文件,还可能是 .swn.swm 等字母。注意这个交换文件的更新不是实时的,因为实时的更新会占用磁盘,影响系统其他正常进程的速度。

在命令行模式中输入 ! 可以执行外部的 shell 命令。

  • :!ls 用于显示当前目录的内容
  • :!rm FILENAME 用于删除名为 FILENAME 的文件
  • :w FILENAME 可将当前 VIM 中正在编辑的文件另存为 FILENAME 文件

Shell变量 运算符 分支 循环 传递参数 函数使用

行首以 # 开头(除#!之外)的是注释。#! 是用于指定当前脚本的解释器,我们这里为 bash,且应该指明完整路径,所以为 /bin/bash

image-20210917105258935

命令分隔符

使用分号 ; 可以在同一行上写两个或两个以上的命令。

1
vim test2.sh

输入如下代码,并保存:

1
2
3
4
5
6
7
8
#!/bin/bash
echo hello; echo there
filename=ttt.sh
if [ -e "$filename" ]; then # 注意: "if"和"then"需要分隔,-e用于判断文件是否存在
echo "File $filename exists."; cp $filename $filename.bak
else
echo "File $filename not found."; touch $filename
fi; echo "File test complete."

终止 case 选项(双分号)

使用双分号 ;; 可以终止 case 选项。

1
vim test3.sh

输入如下代码,并保存。

1
2
3
4
5
6
7
8
#!/bin/bash

varname=b

case "$varname" in
[a-z]) echo "abc";;
[0-9]) echo "123";;
esac

双引号(”)

“STRING” 将会阻止(解释)STRING 中大部分特殊的字符。

单引号(’)

‘STRING’ 将会阻止 STRING 中所有特殊字符的解释,这是一种比使用”更强烈的形式。

斜线(/

文件名路径分隔符。分隔文件名不同的部分(如 /home/bozo/projects/Makefile)。也可以用来作为除法算术操作符。注意在 linux 中表示路径的时候,许多个 / 跟一个 / 是一样的。/home/shiyanlou 等同于 ////home///shiyanlou

反斜线(\

一种对单字符的引用机制。\X 将会“转义”字符 X。这等价于”X”,也等价于’X’。\ 通常用来转义双引号(")和单引号('),这样双引号和单引号就不会被解释成特殊含义了。

  • 符号 说明
  • \n 表示新的一行
  • \r 表示回车
  • \t 表示水平制表符
  • \v 表示垂直制表符
  • \b 表示后退符
  • \a 表示”alert”(蜂鸣或者闪烁)
  • \0xx 转换为八进制的 ASCII 码, 等价于 0xx
  • \" 表示引号字面的意思

转义符也提供续行功能,也就是编写多行命令的功能

命令替换

反引号中的命令会优先执行,如:

1
2
cp `mkdir back` test.sh back
ls

先创建了 back 目录,然后复制 test.sh 到 back 目录。

空命令

1
:

等价于“NOP”(no op,一个什么也不干的命令)。也可以被认为与 shell 的内建命令 true 作用相同。“:”命令是一个 bash 的内建命令,它的退出码(exit status)是(0)

命令组

在括号中的命令列表,将会作为一个子 shell 来运行。

在括号中的变量,由于是在子 shell 中,所以对于脚本剩下的部分是不可用的。父进程,也就是脚本本身,将不能够读取在子进程中创建的变量,也就是在子 shell 中创建的变量。如:

1
vim test20.sh

输入代码:

1
2
3
4
5
6
#!/bin/bash

a=123
( a=321; )

echo "$a" #a的值为123而不是321,因为括号将判断为局部变量

运行代码:

1
2
bash test20.sh
a = 123

在圆括号中 a 变量,更像是一个局部变量。

2.初始化数组

创建数组

1
vim test21.sh

输入代码:

1
2
3
4
#!/bin/bash

arr=(1 4 5 7 9 21)
echo ${arr[3]} # get a value of arr

运行代码:

1
2
bash test21.sh
7

条件测试

条件测试表达式放在 [ ] 中。下列练习中的 -lt (less than)表示小于号。

1
vim test24.sh

输入代码:

1
2
3
4
5
6
7
8
9
#!/bin/bash

a=5
if [ $a -lt 10 ]
then
echo "a: $a"
else
echo 'a>=10'
fi

运行代码:

1
2
bash test24.sh
a: 5

双中括号([[ ]])也用作条件测试(判断)

变量

概念

变量的名字就是变量保存值的地方。引用变量的值就叫做变量替换。

如果 variable 是一个变量的名字,那么 $variable 就是引用这个变量的值,即这变量所包含的数据。

$variable 事实上只是 ${variable} 的简写形式。在某些上下文中 $variable 可能会引起错误,这时候你就需要用 ${variable}

局部变量

这种变量只有在代码块或者函数中才可见。

环境变量

这种变量将影响用户接口和 shell 的行为。

在通常情况下,每个进程都有自己的“环境”,这个环境是由一组变量组成的,这些变量中存有进程可能需要引用的信息。在这种情况下,shell 与一个一般的进程没什么区别。

位置参数

从命令行传递到脚本的参数:$0$1$2$3

$0 就是脚本文件自身的名字,$1 是第一个参数,$2 是第二个参数,$3 是第三个参数,然后是第四个。$9 之后的位置参数就必须用大括号括起来了,比如,${10}${11}${12}

  • $# : 传递到脚本的参数个数
  • $* : 以一个单字符串显示所有向脚本传递的参数。与位置变量不同,此选项参数可超过 9 个
  • $$$$ : 脚本运行的当前进程 ID 号
  • $! : 后台运行的最后一个进程的进程 ID 号
  • $@ : 与 $* 相同,但是使用时加引号,并在引号中返回每个参数
  • $: 显示 shell 使用的当前选项,与 set 命令功能相同
  • $? : 显示最后命令的退出状态。 0 表示没有错误,其他任何值表明有错误。

运算符

5-1-1

运算符说明
-eq检测两个数是否相等
-ne两个数是否不等
-gt大于
-lt小于
-ge大于等于
-le小于等于

逻辑运算

运算符说明
&&逻辑的AND
\\逻辑的OR

字符串运算符

运算符说明
=检测两个字符串是否相等
!=检测两个字符串是否不相等
-z检测字符串长度是否为0
-n检测字符串长度是否不为0
str检测字符串是否为空

文件测试运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
-b file     检测文件是否是块设备文件,如果是,则返回 true。  [ -b $file ] 返回 false。

-c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。

-d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。

-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。

-g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。

-k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。

-p file 检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。

-u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。

-r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。

-w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。

-x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。

-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。

-e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。

流程控制

if

if 语句语法格式:

1
2
3
4
5
6
7
if condition
then
command1
command2
...
commandN
fi

if else

if else 语法格式:

1
2
3
4
5
6
7
8
9
if condition
then
command1
command2
...
commandN
else
command
fi

if-elif-else 语法格式:

1
2
3
4
5
6
7
8
9
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi

删除该目录下处本文件的所有文件

for循环

for 循环一般格式为:

1
2
3
4
5
6
7
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done

image-20210921145536540

image-20210921145551066

创建文件

while循环

while 循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为:

1
2
3
4
while condition
do
command
done

image-20210921145855535

(()) 双括号用于增加算术值,双括号里数值不用带$ 扩展,且可以进行很多算术运算

Bash let 命令,它用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量

case

Shell case 语句为多选择语句。可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。case 语句格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
casein
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
  • 取值后面必须为单词 in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;
  • 取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。

image-20210921150725884

在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell 使用两个命令来实现该功能:breakcontinue

break 命令

break 命令允许跳出所有循环(终止执行后面的所有循环)。

continue 命令与 break 命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环
esac

case 的语法和 C family 语言差别很大,它需要一个 esac(就是 case 反过来)作为结束标记,每个 case 分支用右圆括号,用两个分号表示 break。

image-20210921151953147

函数

shell 中函数的定义格式如下:

1
2
3
4
5
6
7
8
9
[ function ] funname [()]

{

action;

[return int;]

}

说明:

  • 可以带 function fun() 定义,也可以直接 fun() 定义,不带任何参数。
  • 参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return 后跟数值 n(0-255)

  • 函数返回值在调用该函数后通过 $? 来获得

  • 所有函数在使用前必须定义。

函数参数

在 Shell 中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1 表示第一个参数,$2 表示第二个参数…

带参数的函数示例:

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
funWithParam(){
echo "The first parameter is $1 !"
echo "The second parameter is $2 !"
echo "The tenth parameter is $10 !"
echo "The tenth parameter is ${10} !"
echo "The eleventh parameter is ${11} !"
echo "The total number of parameters is $# !"
echo "Outputs all parameters as a string $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
-------------本文结束感谢您的阅读-------------
感谢阅读.

欢迎关注我的其它发布渠道