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环境设置与记录
~/.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 |
设置背景色 |
$ 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 -参数 <文件名>
== [ -参数 <文件名> ]
== [ -参数 <文件名>
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.
#!/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
#!/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
$ ./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.
[Bug]输入回车,将导致if [ = "yes" ]
,而这不是一个合法的条件。应修改为if [ "$timeofday" = "yes" ]
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.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.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 ****
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] )
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
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