一、VIM程序编辑器
-
1.Vim的三种模式
-
2.Vim常用按键说明
-
一般模式
操作 含义 数字 0
或功能键Home
移动到这一行的最前面字符处 $
或功能键End
移动到这一行的最后面字符处 G
移动到这个文件的最后一行 nG
n为数字,移动到这个文件的第n行 gg
移动到这个文件第一行,相当于1G /word
向下寻找一个名为word的字符串 ?word
向上寻找一个名为word的字符串 n
n为英文按键,重复前一个查找的操作 N
N为英文按键,与n方向相反 :n1,n2s/word1/word2/g
n1与n2为数字,在n1与n2之间查找word1字符串,并替换为word2 x,X
x==[Del] X==[Backspace] dd
删除光标所在的一整行 ndd
n为数字,删除光标所在的向下n行 yy
复制光标所在的那一行 nyy
n为数字,复制光标所在的向下n行 p,P
p为将已复制数据在光标下一行粘贴,P为将已复制数据在光标上一行粘贴 u
复原前一个操作(撤销) [Ctrl]+r
重做上一个操作 .
(小数点)重复前一个操作 -
编辑模式
操作 含义 i
进入插入模式,从当前光标所在处插入 a
进入插入模式,从当前光标的下一个字符处插入 [Esc]
退出编辑模式,回到一般模式 -
命令行模式
操作 含义 :w
将编辑的数据写入硬盘文件 :q
离开vim :q!
不保存离开 :wq
保存后离开 :set nu
显示行号 :set nonu
取消行号
-
-
3.块选择
一般模式
操作 含义 V
字符选择或行选择,将光标经过(使用上下左右功能键)的地方反白选择 [Ctrl]+v
块选择,用矩形选择数据 y
将反白的地方复制 d
将反白的地方删除 p
在光标处粘贴 -
4.多窗口功能
命令行模式下
- 在命令行模式中输入
:sp{filename}
.如果新窗口启动另一文件,输入文件名,否则仅输入:sp
出现同一个文件的两个窗口。
[Ctrl]+w+↑
光标移动到上面窗口
[Ctrl]+w+↓
光标移动到下面窗口
[Ctrl]+w+q
退出,关闭当前窗口
- 在命令行模式中输入
-
5.Vim环境设置与记录
- 记录在vim内操作的文件
~/.viminfo
vim环境设置参数操作 含义 :set nu/:set nonu
设置与取消行号 :set hlsearch/:set nohlsearch
设置与取消高亮查找 hlsearch == high light search :set autoindent/:set noautoindent
设置与取消自动缩排(回车后,光标在与上一行的第一个非空格符处对齐,而不是出现在行首) :set ruler
设置右下角状态栏说明 :set showmode
设置左下角状态说明 :set all
显示目前所有环境参数设置值 :set
显示与系统默认值不同的参数 :syntax on/syntax off
语法高亮色 :set bg=dark/:set bg=light
设置背景色
- 记录在vim内操作的文件
-
6.vim常用命令示意图
二、认识与学习bash
变量
$ a=Hello
$ echo $a
Hello #查看变量内容
$ a = 9
a: command not found
$ a= 9
9: command not found #=两边不能有空格
$ a=9
$ echo $a
9
$ a="ds fd s"
$ echo $a
ds fd s #字符串有空格须用引号括起 ''或""
$ a=8+9+1+3+4+5+6
$ echo a
a
$ echo $a
8+9+1+3+4+5+6
$ read a
qwert #用户输入赋值给a 回车结束
$ echo $a
qwert
-
引号的使用
字符串通常被放在" "
中,以防止变量被空白符号分开,同时允许$扩展。
variable.sh
#!/bin/sh myvar="Hi there" echo $myvar echo "$myvar" echo '$myvar' echo \$myvar echo Enter some text read myvar echo '$myvar' now equals $myvar exit 0
执行如下
$ ./variable.sh Hi there Hi there $myvar $myvar Enter some text Hello World $myvar now equals Hello World
-
环境变量
环境变量 说明 $HOME
当前用户家目录 $PATH
以冒号分隔的用来搜索命令的目录列表 $PS1
命令提示符 $
$PS2
二级提示符 >
$IFS
输入域分隔符 sp
tab
enter
$0
shell脚本名字 $#
传递给脚本的参数个数 $$
shell脚本的进程号 -
参数变量
参数变量 说明 $1
,$2
,...
脚本程序参数 $*
在一个变量中列出所有参数,各参数之间用 $IFS
中的第一个字符分隔开$@
$*
的变体,不使用$IFS
变量,即使$IFS
为空,参数也不会挨在一起$ echo $IFS #这里是一个空格 $ set foo bar bad $ echo "$@" foo bar bad $ echo "$*" foo bar bad $ IFS='' $ echo "$*" foobarbad $ echo "$@" foo bar bad $ unset IFS $ echo "$*" foo bar bad $ IFS=' ' $ echo "$*" foo bar bad $ set zxc vbn mjg $ echo "$*" zxc vbn mjg
try_var.sh
#!/bin/sh arg="Hello" echo $arg echo "The program $0 is now running" echo "The seconed parameter was $2" echo "The first parameter was $1" echo "The parameter list was $*" echo "The parameter list was $@" echo "The user's home directory is $HOME" echo "Please input a new greeting" read arg echo "$arg" now equals $arg echo "The script is now complete" exit 0
执行如下
$ chomd +x try_var.sh $ ./try_var.sh 111 ok hbk hhh Hello The program ./try_var.sh is now running The seconed parameter was ok The first parameter was 111 The parameter list was 111 ok hbk hhh The parameter list was 111 ok hbk hhh The user's home directory is /home/hyper Please input a new greeting AI AI now equals AI The script is now complete
条件
- test 或 [ 命令
test -参数 <文件名>
==[ -参数 <文件名> ]
==[ -参数 <文件名>
conditions.sh
#!/bin/sh if [ -f /bin/bash ] then echo "file /bin/bash exists." fi if test -d /bin/bash then echo "/bin/bash is a directory." else echo "/bin/bash is NOT a directory." fi
执行如下
$ vim conditions.sh $ chmod +x conditions.sh $ ./conditions.sh file /bin/bash exists. /bin/bash is NOT a directory.
控制结构
- if 语句
#!/bin/sh echo "Is it morning? Please answer yes or no" read timeofday if [ $timeofday = "yes" ]; then echo "Good morning." else echo "Good afternoon." fi exit 0
- elif 语句
#!/bin/sh echo "Is it morning? Please answer yes or no" read timeofday if [ $timeofday = "yes" ] then echo "Good morning." elif [ $timeofday = "no" ] then echo "Good afternoon." else echo "Sorry, $timeofday not recognized. Enter yes or no." exit 1 fi exit 0
- 潜藏的bug
如果不回答问题,直接按下回车键,将看到以下信息:
[Bug]输入回车,将导致$ ./elif.sh Is it morning? Please answer yes or no ./elif.sh: line 4: [: =: unary operator expected ./elif.sh: line 7: [: =: unary operator expected Sorry, not recognized. Enter yes or no.
if [ = "yes" ]
,而这不是一个合法的条件。应修改为if [ "$timeofday" = "yes" ]
- for 语句
for1.sh
#!/bin/sh for foo in bar fub 43 do echo $foo done exit 0
执行如下
$ ./for1 bar fub 43
for2.sh
#!/bin/sh for foo in "bar fub 43" do echo $foo done exit 0
执行如下
$ ./for2 bar fub 43
for3.sh
打印当前目录中所有以字母f
开头,以.sh
结尾的脚本文件#!/bin/sh for file in $(ls f*.sh) do lpr $file done exit 0
执行如下
$ ./for3.sh lpr: Error - No default destination. lpr: Error - No default destination. lpr: Error - No default destination. lpr: Error - No default destination.
lpr
(line printer,按行打印)实用程序用来将一个或多个文件放入打印队列等待打印。未连接打印机,所以出错,将lpc
改为echo
得到以下结果$ ./for3.sh first.sh for1.sh for2.sh for3.sh
- while 语句
while.sh
#!/bin/sh echo "Enter password" read trythis while [ "$trythis" != "secret" ];do echo "Sorry,try again" read trythis done exit 0
$ ./while.sh Enter password qwert Sorry,try again secret
- until 语句
循环将反复执行直到条件为真
until.sh
#!/bin/bash until who | grep "$1" > /dev/null do sleep 60 done # now ring the bell and announce the expected user. echo -e '\a' echo "**** $1 has just logged in ****" exit 0
$ ./until.sh **** has just logged in ****
- case 语句
将最精确的匹配放在最开始,最一般化的匹配放在最后。
case1.sh
#!/bin/sh echo "Is it morning? Please answer yes or no " read timeofday case "$timeofday" in yes) echo "Good Morning";; no ) echo "Good Afternoon";; y ) echo "Good Morning";; n ) echo "Good Afternoon";; * ) echo "Sorry,answer not recongized";; esac exit 0
case2.sh
#!/bin/sh echo "Is it morning? Please answer yes or no " read timeofday case "$timeofday" in yes | y | Yes | YES) echo "Good Morning";; n* | N* ) echo "Good Afternoon";; * ) echo "Sorry,answer not recongized";; esac exit 0
case3.sh
#!/bin/sh echo "Is it morning? Please answer yes or no " read timeofday case "$timeofday" in yes | y | Yes | YES ) echo "Good Morning" echo "Up bright and early this morning" ;; [nN]* ) echo "Good Afternoon";; * ) echo "Sorry,answer not recongized" echo "Please answer yes or no" exit 1 ;; esac exit 0
case3.sh 执行如下
可以看出$ ./case3.sh Is it morning? Please answer yes or no y Good Morning Up bright and early this morning $ ./case3.sh Is it morning? Please answer yes or no Y Sorry,answer not recongized Please answer yes or no $ ./case3.sh Is it morning? Please answer yes or no n Good Afternoon $ ./case3.sh Is it morning? Please answer yes or no N Good Afternoon $ ./case3.sh Is it morning? Please answer yes or no nNNNNN Good Afternoon $ ./case3.sh Is it morning? Please answer yes or no NNNNNNNNNNNNNNN Good Afternoon
[]
中的字母任意匹配,可将Morning
的匹配项改为如下[yY] | [Yy][Ee][Ss] )
- 命令列表
- AND 列表
state1
&&
state2
&&
state3
&&
...
state1
为真
则继续向右执行,否则有一假
则停止执行。
and.sh
#!/bin/sh touch file_one rm -f file_two if [ -f file_one ] && echo "hello" && [ -f file_two ] && echo " there" then echo "in if" else echo "in else" fi exit 0
执行如下
$ ./and.sh hello in else
- OR 列表
state1
||
state2
||
state3
||
...
state1
为假
则继续向右执行,否则有一真
则停止执行。
or.sh
#!/bin/sh rm -f file_one if [ -f file_one ] || echo "hello" || echo " there" then echo "in if" else echo "in else" fi exit 0
执行如下
$ ./or.sh hello in if
AND
结合OR
使用
[ -f file_one ] && command for true || command for false
相当于C
语言? :
表达式
- 语句块
get_confirm && { grep -v "$cdcatnum" $tracks_file > $temp_file cat $temp_file > $tracks_file echo add_record_tracks }
函数
foo.sh
#!/bin/sh foo() { echo "Function foo is executing" } echo "script starting" foo echo "script ended" exit 0
执行如下
$ ./foo.sh script starting Function foo is executing script ended
foo2.sh
#!/bin/sh sample_text="global variable" foo() { local sample_text="local variable" echo "Function foo is executing" echo $sample_text } echo "script starting" echo $sample_text foo echo "script ended" echo $sample_text exit 0
执行如下
$ ./foo2.sh script starting global variable Function foo is executing local variable script ended global variable
return.sh
#!/bin/sh yes_or_no() { echo "Is your name $* ?" while true do echo -n "Enter yes or no: " read x case "$x" in y | yes ) return 0;; n | no ) return 1;; * ) echo "Answer yes or no" esac done } echo "Original paramemters are $*" if yes_or_no "$1" then echo "Hi $1, nice name" else echo "Never mind" fi exit 0
执行如下
$ ./return.sh Rick Neil Original paramemters are Rick Neil Is your name Rick ? Enter yes or no: y Hi Rick, nice name $ ./return.sh Rick Neil Original paramemters are Rick Neil Is your name Rick ? Enter yes or no: n Never mind
- 输入
y
返回0
为什么会进入if
分支? - 输入
n
返回1
为什么会进入else
分支?
- 输入
每一条
Shell
命令,不管是Bash
内置命令(例如cd
、echo
),还是外部的Linux
命令(例如ls
、awk
),还是自定义的Shell
函数,当它退出(运行结束)时,都会返回一个比较小的整数值给调用(使用)它的程序,这就是命令的退出状态(exit statu)。
很多 Linux 命令其实就是一个C语言程序,熟悉C语言的读者都知道,main() 函数的最后都有一个return 0,如果程序想在中间退出,还可以使用exit 0,这其实就是C语言程序的退出状态。当有其它程序调用这个程序时,就可以捕获这个退出状态。
if 语句的判断条件,从本质上讲,判断的就是命令的退出状态。
按照惯例来说,退出状态为 0 表示“成功”;也就是说,程序执行完成并且没有遇到任何问题。除 0 以外的其它任何退出状态都为“失败”。
之所以说这是“惯例”而非“规定”,是因为也会有例外,比如 diff 命令用来比较两个文件的不同,对于“没有差别”的文件返回 0,对于“找到差别”的文件返回 1,对无效文件名返回 2。
有编程经验的读者请注意,Shell 的这个部分与你所熟悉的其它编程语言正好相反:在C语言、C++、Java、Python 中,0 表示“假”,其它值表示“真”。
在 Shell 中,有多种方式取得命令的退出状态,其中 $? 是最常见的一种。我们不妨来看一下它的退出状态。请看下面的代码:
#!/bin/bash
read a
read b
(( $a == $b ));
echo "退出状态:"$?
运行结果1:
26
26
退出状态:0
运行结果2:
17
39
退出状态:1
命令
-
break 命令
用于跳出for
,until
,while
,可接收数值参数表示跳出循环的层数
break.sh
#!/bin/sh rm -rf fred* echo > fred1 echo > fred2 mkdir fred3 echo > fred4 for file in fred* do if [ -d "$file" ]; then break; fi done echo first directory starting fred was $file rm -rf fred* exit 0
执行如下
$ ./break.sh first directory starting fred was fred3
-
: 命令
空命令,偶尔用在条件逻辑中表示true
#!/bin/sh rm -f fred if [ -f fred ]; then : else echo file fred did not exist fi exit 0
执行如下
$ ./:.sh file fred did not exist
-
continue 命令
用于跳过本次for
,until
,while
,可接收数值参数表示跳出循环的层数
break.sh
#!/bin/sh rm -rf fred* echo > fred1 echo > fred2 mkdir fred3 echo > fred4 for file in fred* do if [ -d "$file" ]; then break; fi done echo first directory starting fred was $file rm -rf fred* exit 0
执行如下
$ ./break.sh first directory starting fred was fred3
-
. 命令
环境设置,类似于C/C++
中的#include
-
echo 命令
终端输出 -
eval 命令
对参数求值 -
exec 命令
将当前shell
替换为一个不同的程序exec wall "Thanks for all the fish"
修改当前文件描述符
exec 3< afile
-
exit n 命令
使脚本程序以退出码n结束退出码 说明 126 文件不可执行 127 命令未找到 128+ 出现一个信号 0 成功 -
export 命令
导出变量到子shell
export2.sh
#!/bin/sh echo "$foo" echo "$bar"
export1.sh
#!/bin/sh foo="The first meta-syntactic variable" export bar="the second meta-synatactic variable" export2
执行如下
$ ./export1 ./export1: line 4: export2: command not found
-
expr 命令
表达式求值 -
printf 命令
$ printf "%s\n" hello hello $ printf "%s %d\t%s" "Hi There" 15 people Hi There 15 people
-
return 命令
若不制定返回参数,则默认返回最后一条命令的退出码。 -
set 命令
设置shell参数变量 -
shift 命令
将所有参数变量左移一个位置 -
trap 命令
用于在接受到信号后将要采取的行动 -
unset 命令
从环境变量中删除变量或函数 -
find
grep
正则表达式
-
find
find [path] [options] [tests] [actions]
- 在
当前目录
下查找以字母c
开始的文件
:$ find . -name "c*" -type f ./conditions.sh ./case3.sh ./case2.sh ./case1.sh
- 在当前目录下查找比文件
foo.sh
新的文件
:$ find . -newer foo.sh -type f -ls 21102687 4 -rwxr-xr-x 1 hyper hyper 126 2月 12 20:35 ./export1.sh 21102688 4 -rwxr-xr-x 1 hyper hyper 46 2月 12 20:33 ./export2.sh 21102684 4 -rwxr-xr-x 1 hyper hyper 276 2月 12 15:31 ./break.sh 24772694 4 -rwxr-xr-x 1 hyper hyper 238 2月 12 14:19 ./foo2.sh 24772695 4 -rwxr-xr-x 1 hyper hyper 499 2月 12 14:29 ./return.sh 21102685 4 -rwxr-xr-x 1 hyper hyper 129 2月 12 15:38 ./:.sh
- 在
当前目录
下查找以字母c
开始的 或 比文件foo.sh
新的文件
:$ find . \( -newer foo.sh -or -name "c*" \) -type f -ls 24772680 4 -rwxr-xr-x 1 hyper hyper 184 2月 11 20:52 ./conditions.sh 21102687 4 -rwxr-xr-x 1 hyper hyper 126 2月 12 20:35 ./export1.sh 21102688 4 -rwxr-xr-x 1 hyper hyper 46 2月 12 20:33 ./export2.sh 21102684 4 -rwxr-xr-x 1 hyper hyper 276 2月 12 15:31 ./break.sh 24772689 4 -rwxr-xr-x 1 hyper hyper 534 2月 12 13:07 ./case3.sh 24772688 4 -rwxr-xr-x 1 hyper hyper 301 2月 12 13:06 ./case2.sh 24772694 4 -rwxr-xr-x 1 hyper hyper 238 2月 12 14:19 ./foo2.sh 24772695 4 -rwxr-xr-x 1 hyper hyper 499 2月 12 14:29 ./return.sh 24772687 4 -rwxr-xr-x 1 hyper hyper 324 2月 12 12:46 ./case1.sh 21102685 4 -rwxr-xr-x 1 hyper hyper 129 2月 12 15:38 ./:.sh
- 在
-
grep
grep [options] PATTERN [FILES]
options meaning -c
输出匹配行的数目 -v
匹配模式取反——搜索不匹配的行 -i
忽略大小写 ...
...
- 在
foo.sh
文件中匹配in
出现的行$ grep in ./foo.sh #!/bin/sh echo "Function foo is executing" echo "script starting"
- 在
foo.sh
和foo2.sh
文件中匹配in
出现的总行数$ grep -c in ./foo.sh ./foo2.sh ./foo.sh:3 ./foo2.sh:3
- 在
foo.sh
和foo2.sh
文件中匹配in
不出现的总行数$ grep -c -v in ./foo.sh ./foo2.sh ./foo.sh:6 ./foo2.sh:11
- 在
-
正则表达式
char meaning ^ 指向一行的开头 $ 指向一行的结尾 . 任意单个字符 [] 括号内包含一个字符范围,其中任何一个字符都可被匹配 若使用上述字符作普通字符,须在其前加
\
匹配模式 含义 [:alnum:]
字母与数字字符 [:alpha:]
字母 [:ascii:]
ASCII字符 [:blank:]
空格或制表符 [:cntrl:]
ASCII控制字符 [:digit:]
数字 [:graph:]
非控制、非空格字符 [:lower:]
小写字母 [:print:]
可打印字符 [:punct:]
标点符号 [:space:]
空白字符 [:upper:]
大写字母 [:xdigit:]
十六进制数字 扩展匹配
-E
选项选项 含义 ?
匹配是可选的,但最多匹配一次 *
必须匹配0此或多次 +
必须匹配1此或多次 {n}
必须匹配n次 {n,}
必须匹配n次或n+次 {n,m}
必须匹配n~m次 $ cat foo2.sh #!/bin/sh sample_text="global variable" foo() { local sample_text="local variable" echo "Function foo is executing" echo $sample_text } echo "script starting" echo $sample_text foo echo "script ended" echo $sample_text exit 0
-
在上述文件
foo2.sh
中查找以字母e
开始的行:$ grep ^e ./foo2.sh echo "script starting" echo $sample_text echo "script ended" echo $sample_text exit 0
-
在上述文件
foo2.sh
中查找以字符"
结尾的行:$ grep \"$ ./foo2.sh sample_text="global variable" local sample_text="local variable" echo "Function foo is executing" echo "script starting" echo "script ended"
-
在上述文件
foo2.sh
中查找以字母o
结尾的单词:$ grep o[[:blank:]] ./foo2.sh echo "Function foo is executing" echo $sample_text echo "script starting" echo $sample_text echo "script ended" echo $sample_text
-
在上述文件
foo2.sh
中查找以字母fo
开始的由3
个字母组成的单词:$ grep fo.[[:space:]] ./foo2.sh echo "Function foo is executing"
-
在上述文件
foo2.sh
中查找只由6
个字符长的全部小写字母
组成的单词:$ grep -E [a-z]\{6\} ./foo2.sh sample_text="global variable" local sample_text="local variable" echo "Function foo is executing" echo $sample_text echo "script starting" echo $sample_text echo "script ended" echo $sample_text
命令的执行
- 算术扩展
#!/bin/sh x=0 while [ "$x" -ne 10 ] do echo $x x=$(($x+1)) done exit 0