0Shell命令

#! bin/sh

bach

自动补全

bash-complete

历史命令

history -c / !id

别名功能

alias / unalias / ~/.bashrc

初始化

1. /etc/profile
2. /etc/bashrc
3. ~/.profile
4. ~/.bash_login
5. ~/.bash_profile
6. ~/.bashrc
7. ~/.bash_logout
快捷键
ctrl+A == ALT+A	把光标移动到命令行开头
ctrl+E 把光标移动到命令行结尾
ctrl+C == ALT+C 强制终止当前的命令
ctrl+L 清屏,相当于clear命令
ctrl+U 删除或剪切光标之前的命令
ctrl+K 删除或剪切光标之后的内容
ctrl+Y 粘贴ctrl+U或ctul+K剪切的内容
ctrl+R 在历史命令中搜索
ctrl+D 退出当前终端
ctrl+Z 暂停,并放入后台 jobs查看bg[id]运行
ctrl+S 暂停屏幕输出
ctrl+Q 恢复屏幕输出
ALT+B – 光标移动到所在单词词首
ALT+D – 关闭空的终端(也就是它会关闭没有输入的终端)也删除光标后的全部字符
ALT+F – 移动到光标所在单词词末
ALT+T – 交换最后两个单词
ALT+U – 将单词内光标后的字母转为大写
ALT+L – 将单词内光标后的字母转为小写
ALT+R – 撤销对从历史记录中带来的命令的修改
ALT+. – 使用上一条命令的最后一个单词。

重定向

文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)

> 覆盖 == 1>  
>> 追加    
2>&1 把标准错误输出 重定向 到标准输出 
&>file == >&file 输出所有结果
命令 说明
command > file 将输出重定向到 file。
command < file 将输入重定向到 file。
command >> file 将输出以追加的方式重定向到 file。
command > file 2>&1 以追加的方式,把结果保存到 file
command >> file 2>&1 以追加的方式,把结果保存到 file
n > file 将文件描述符为 n 的文件重定向到 file。
n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m 将输出文件 m 和 n 合并。
n <& m 将输入文件 m 和 n 合并。
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。
command < file1 >file2 将正确结果输出到file1,错误结果输出到file2
command >> file1 2>>file2 将正确结果输出到file1,错误结果输出到file2
command > file1 2>file 不推荐,正确和错误结果会相互覆盖
command > /dev/null 执行命令,取消输出结果
command > /dev/null 2>&1 屏蔽 stdout 和 stderr “禁止输出”
command << delimiter # 将两个 delimiter 之间的内容(document) 作为输入传递给 command
document # 结尾的delimiter 一定要顶格写,前后不能有任何字符
delimiter # 开始的delimiter前后的空格会被忽略掉
$ wc -l << EOF		# 计算 Here Document 的行数
欢迎来到
菜鸟教程
www.runoob.com
EOF
3 # 输出结果为 3 行
#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
cat << EOF
欢迎来到
菜鸟教程
www.runoob.com
EOF
# 输出
欢迎来到
菜鸟教程
www.runoob.com
统计文本
wc -c / -w / -l < file			# 字节 / 单词 / 行
管道
|		  	传递结果
| tee 同时输出 / 传递
|| 前面命令执行成功后面不执行
&& 前面执行成功后执行后面命令
; 依次执行命令
通配符
通配符 含义 实例
* 匹配 0 或多个字符 a*b,a与b之间可以有任意长度的任意字符, 也可以一个也没有, 如 aabcb, axyzb, a012b, ab
? 匹配任意单个字符 a?b,a与b之间有且只有一个字符, 可以是任意字符, 如 aab, abb, acb, a0b
[list] 匹配 list 中的任意单个字符 a[xyz]b,a与b之间必须也只能有一个字符, 但只能是 x 或 y 或 z, 如 axb, ayb, azb
[!list] 匹配除 list 中的任意单一字符 a[!0-9]b,a与b之间必须也只能有一个字符, 但不能是阿拉伯数字, 如 axb, aab, a-b
[c1-c2] 匹配 c1-c2 中的任意单一字符 a[0-9]b,匹配0与9之间其中一个字符,如 a0b, a1b… a9b
{s1,s2,…} 匹配 s1 或 s2 (或更多)中的一个字符串 a{abc,xyz,123}b,a与b之间只能是abc或xyz或123这三个字符串之一
脚本调试
sh [ -n -v -x ] # -n 检查语法 -v 执行前先输出脚本内容 -x 输出脚本内容
作业脱机管理

nohup忽略所有挂断信号

jobs 新终端

nohup .sh >log.txt 2&1 &有&位于后台,没有则位于前台

screen
screen [-AmRvx -ls -wipe][-d <作业名称>][-h <行数>][-r <作业名称>][-s ][-S <作业名称>]
screen -dmS session_name # 创建会话(-m强制)
screen -X -s session_name quit
screen -S yourname # 新建一个叫yourname的session
screen -ls # 列出当前所有的session
screen -r yourname # 回到yourname这个session
screen -d yourname # 远程detach某个session
screen -d -r yourname # 结束当前session并回到yourname这个session
参数说明
-A 将所有的视窗都调整为目前终端机的大小
-d <作业名称> 将指定的screen作业离线
-h <行数> 指定视窗的缓冲区行数
-m 即使目前已在作业中的screen作业,仍强制建立新的screen作业
-r <作业名称> 恢复离线的screen作业
-R 先试图恢复离线的作业。若找不到离线的作业,即建立新的screen作业
-s 指定建立新视窗时,所要执行的shell
-S <作业名称> 指定screen作业的名称
-v 显示版本信息
-x 恢复之前离线的screen作业
-ls或–list 显示目前所有的screen作业
-wipe 检查目前所有的screen作业,并删除已经无法使用的screen作业
screen session 下的快捷键
C-a ? 显示所有键绑定信息
C-a w 显示所有窗口列表
C-a C-a 切换到之前显示的窗口
C-a c 创建一个新的运行shell的窗口并切换到该窗口
C-a n 切换到下一个窗口
C-a p 切换到前一个窗口(与C-a n相对)
C-a 0..9 切换到窗口0..9
C-a a 发送 C-a到当前窗口
C-a d 暂时断开screen会话
C-a k 杀掉当前窗口
C-a [进入拷贝/回滚模式
shell变量

变量名=变量值
变量名不能以数字开头
左右两侧不能有空格
变量的值如果有空格,必须用引号包含

自定义变量
  • 查看变量:echo $变量名 set(所有变量: 包括自定义变量和环境变量)

  • 取消变量: unset 变量名

  • 作用范围: 仅当前shell 生效

环境变量
/etc/profile
~/.bashrc
~/.bash
~/.bashlogout
位置变量
.sh [$1] [$2]
$* # 所有参数
$# # 参数个数
$$ # 进程PID
预定义变量
read 从键盘读入变量值

read -n(不换行) -p(提示语句) -n(字符个数) -t(等待时间) -s(不回显) -u(文件描述符)

read 变量名
read -p "提示信息:" 变量名
read -t 5 -p "提示信息:" 变量名 # 超时
read -n 2 变量名 # 字符判断
read -s # 读入的字符隐藏
定义引用变量

" "弱引用

``强引用 = $()

touch `date +%F`_file1.txt # 加时间戳
变量运算
整数运算
expr
expr1 + 2
expr $num1 + $num2 # + - \* / %
$(())
echo $((num1 + num2))
$[]
echo $[5+2]
let
let sum=2+3;echo $sum
小数运算
echo "2*4" |bc
echo "scale=2;6/4" |bc
echo "print 5.0/2" |python
变量”内容”的删除和替换
内容的删除
name=www.baidu.com.cn
echo ${name} #获取变量值
echo ${#name} #获取变量长度
echo ${name#*.} #从左往右最短匹配
echo ${name##*.} #从左往右最长匹配
echo ${name%.*} #从右往左最短匹配
echo ${name%%.*} #从右往左最短匹配
echo ${name:0:3} #从0索引切到3索引,包前不报后,切出前三位
echo ${name:0} #从0索引处开始截取

img

x=${name-haha}
echo $x
unset name #此时,无name变量
x=${name-haha}
echo $x
name= #此时,虽然有name变量,但是值为空
x=${name-haha}
echo $x
变量替换
${变量名:-新的变量值} 
echo ${name/baidu/qq} # 变量内容替换
echo ${name//w/W} # 变量内容替换贪婪匹配
echo $(var1-/=/+aaa) # 变量有值需加号重新赋值
i++ 和 ++i
先赋值,在运算;先运算,后赋值

Shell函数

function name {
commands
[return value]
}

shell循环

for
for 变量 in 值集合
do
执行命令
done
while (条件为真)
while 条件测试
do
执行命令
done
until (条件为假)
declare -i i=10
dexlare -i sum=0
until ((i>10)) #i值未超过10则进入循环
do
let sum+=i
let ++i
done
echo $sum
shell循环控制
break

退出所有循环

continue

退出当前循环

exit

退出执行

shift

shift命令表示参数向左偏移,后面可跟数字(数字大小在参数个数范围内)

#!/bin/sh
echo "first args:$1, args counts: $#"
shift 2
echo "first args:$1, args counts: $#"
$ sh shift.sh 1 2 3 4 5
first args:1, args counts: 5
first args:3, args counts: 3

shell编程之条件结构

#符号详解
() 在子shell中运行
``(a=1);echo $a,结果是空,因为a=1不是在当前shell中运行的(a=1);(echo $a)也是空的
``小技巧:(cd $path, ``do` `something) 可以让不切换当前目录而在其它目录干点别的事儿~
``() 还有个功能是数组的赋值:比如a=(1 3 5),那么${a[0]}=1;${a[1]}=3;${a[2]}=5,需要注意的是,下标是从0开始的。
(()) 表达式计算
``a=1;((a++));echo $a,这时a就是2了。
<() 和 >() 进程代入,可以把命令的执行结果当成文件一样读入
``比如comm前一般需要sort,那就可以这样comm <(sort 1.lst) <(sort 2.lst)
``或者是paste <(cut -t2 file1) <(cut -t1 file1),和管道差不多,但是支持多个输入。
$() $(cmd) 执行cmd的结果
``比如cmd是echo ls,那么就是执行ls,比如file $(which bash),which bash的结果是/bin/bash,
``所以file $(which bash)等于file /bin/bash。如果你$(ls),而且你的当前目录下只有a b两个文件,
``那么就是执行a b,然后系统会提示,命令没找到。$() 基本和 `` 等价。
$(()) 表达式扩展,
``和(())很相似,但是这个是有点不同,$(())不能直接$((b++)),例如:b=1;echo $((++b))
``这时b等于2,显示的也是2,b=1; echo $((b++))这时b等于2,显示的是1.
[] 和 [[]],[] 就是 test,[]和[[]]都是条件表达式,不过[[]]有比[]高的容错性, [ -a|-o] [[ && | || ]]
``如果a为空,那么[ $a -eq 0 ]会报错,但是[[ $a -eq 0 ]]不会,所以一般都会使用[[]]或者是
``[ ``"$a"` `-eq 0 ],[[]]支持的功能也比 [] 多,比如[[ aaa =~ a{3} ]],[] 还有一种用途,
``如果你的当前目录下有a1-a9九个文件,你可以用a[1-9]来替代这九个文件。
``有点需要注意,你不能用a[1-20]来代替a1- a20,必须要a[1-9] a1[0-9] a20。
``但是需要注意的是 [[]] 数字进制转换的坑~
$[] 是 $(()) 的过去形式,现在已经不建议使用。
{n..m} {1..30} 就是1-30,或者是/{,s}bin/表示/bin/和/sbin/,ab{c,d,e}表示abc、abd、abe,
``小技巧:文件备份:cp a.sh{,.bak}
``而 { cmd1; cmd2; } 的作用是定义一个命令组,一般用在单行的条件表达式中:
``[[ 1 -eq 2 ]] && echo True || { echo False; echo ``"Program will exit!"``; }
``其实 shell 函数的语法也是它的变体:
``a(){ i=$1; echo $((i++)); echo $((++i)); } && a 1
${} 变量的Parameter Expansion,
``用法很多,最基本的 ${``var``}1,防止变量扩展冲突,具体可以查看man bash
(){} 括号左边与命令之间要有空格

小括号尽在当前命令行生效

大括号在当前终端生效

shell测试表达式
条件测试语法
条件测试语法 #说明
test <测试表达式> test命令和后面<内容>之间至少有一个空格
[ <测试表达式> ] 单中括号进行条件测试表达式,[]的边界和内容之间至少要有一个空格
[[ <测试表达式> ]] 双括号,[[]]的边界和内容也是要有空格
((<测试表达式>)) 双小括号,两端不用空格

语法1中的test命令和语法2中的[]是等价的。语法3中的[[]]为扩展的test命令,语法4中的(())常用于计算
[]中可以使用通配符等进行模式匹配,这是其区别其他集中语法格式的地方
&&、||、>、<等操作符可以应用于[[]]中,但不能应用于[]中,在[]中一般用-a、-o、-gt(用于整数)、-lt(用于整数)代替上述操作符
对于整数的关系运算,也可以使用shell的算术运算符(())

常用的文件测试操作符
常用的文件测试操作符 说明
-d 文件,d的全称是directory 文件存在且为目录则为真
-f 文件,f的全称是file 文件存在且为普通文件则为真
-e 文件,e的全称是exist 文件存在则为真,-e不辨别是文件还是目录
-r 文件,r的全称是read 文件存在且可读,则为真
-s 文件,s的全称是size 文件存在且文件大小不为0,则为真
-w 文件,w的全称是write 文件存在且可写,则为真
-x 文件,x的全称是executable 文件存在且可执行,则为真
-L 文件,L的全称是Link 文件存在且为链接文件,则为真
f1 -nt f2,nt的全称是newer than 文件f1比文件f2新,则为真;根据文件修改时间对比
f1 -ot f2,nt的全称是older than 文件f1比文件f2旧,则为真;根据文件修改时间对比

如果需要获取更多信息,则使用man test

test -d /home
echo $?
字符串测试表达式
常用字符串操作符 #说明
-z “字符串” 如果字符串长度为0则为真
-n “字符串” 如果字符串长度不为0则为真
“字符串1” = “字符串2” 如果字符串1等于字符串2则为真,可以使用==代替=
“字符串1” != “字符串2” 如果字符串1不等于字符串2则为真,不能使用!==代替!=
[ -n "abc" ] && echo 1 || echo 0
1 #-n是不为空则为真,字符串长度为abc,所以长度不是为0,为真输出1
test -n "aa" && echo 1 || echo 0
1
test -n "" && echo 1 || echo 0
0 #字符串为空,不为真,数以输出0
var="test"
[ -n "$var" ] && echo 1|| echo 0
1
[ -z "$var" ] && echo 1|| echo 0
0 #-z是为空值为真,不为空值为假,所以输出0,
[ "aa" = "aa" ] && echo 1 || echo 0
1 #字符串相等,所以长度为0,为真
整数二元比较操作符
在test及[]中使用的比较符号 在[[]]和(())中使用的比较符号 说明
-eq == 或 = 相等,全称equal
-ne != 不相等,全称not qeual
-gt > 大于,全称greater than
-ge >= 大于等于,全称为greater equal
-lt < 小于,全称less than
-le <= 小于等于,全称less equal
[ 2 > 3 ] && echo 1 || echo 0
1 #结果应该返回0,但是不转义返回了1是错误的
[ 2 \> 3 ] && echo 1 || echo 0
0 #进行转义之后输出正确
[ 2 < 1 ] && echo 1 || echo 0
[ 2 \< 1 ] && echo 1 || echo 0
0
常用的逻辑操作符
在test及[]中使用的比较符号 在[[]]和(())中使用的比较符号 说明
-a && and,且,两端都为真,则结果为真
-o || or,或,两端有一个为真,则结果为真
! ! not,非,两端相反,则结果为真
逻辑操作符前后的表达式是否成立,一般用真假来表示
“!”的中文意思是反,即与一个逻辑值相反的逻辑值
-a的中文意思是“与”(and或&&),前后两个逻辑值都为“真”,综合返回值才为真,否则为假
-o的中文意思是“或”(or或||),前后两个逻辑值只要有一个为真,返回值就为真
连接两行[]、test或[[]]的表达式可用&&或||
f1=/etc/rc.local
f2=/etc/services
[ -f "$f1" -a -f "$f2" ] && echo 1 || echo 0
1  #判断如果f2和f2变量的文件存在且为文件的话,就为真,输出1,如果一个不为真,那么久不为真,就输出0
[[ -f "$f1" && -f "$f2" ]] && echo 1 || echo 0
1  #在[[]]双中括号中就可以使用&&
[ -f "$f1" ]&&[ -f "$f2" ] && echo 1 || echo 0
1  #或者在两个[]之间使用&&也可以
shell分支语句
if
if [ 条件判断式];then
程序
fi
或者
if [ 条件判断式]
then
程序
fi
#!/bin/bash
test=$(env | grep USER |cut -d "=" -f 2)
if [ "$test" == "root" ]
then
echo "you are root"
fi
双分子语句
if [ 条件判断 ]
then
commands
else
commands
fi
#!/bin/bash
#date 2020-2-24
#描述:测试主机存活状态
read -p "请输入一个ip:" ip
ping -c 1 $ip &>/dev/null
if [ $? -eq 0 ]
then
echo "ip主机存活"
else
echo "ip主机未存活,请尽快查看主机情况"
fi
shell分支case语句
case $变量名 in
"值 1")
;;
如果变量的值等于值1,则执行程序1,值
2")
如果变量的值等于值2,则执行程序2
…省略其他分支…
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
vi sh/case.sh
#!/bin/bash
#判断用户输入
read -p "Please choose yes/no: " -t 30 cho
#在屏幕上输出"请选择yes/no",然后把用户选择赋予变量cho
case $cho in
#判断变量cho的值
"yes")
#如果是yes
echo "Your choose is yes!"
#则执行程序1
;;
"no")
#如果是no
echo "Your choose is no!"
#则执行程序2
;;
*)
#如果既不是yes,也不是no
echo "Your choose is error!"
#则执行此程序
;;
esac

shell数组

hexo不允许双}}出现,所以我也无能为力,可以下载查看

正则表达式

星号*:

匹配它前面的字符串或正则表达式任意次(包括0次)。
比如:1122*
可能匹配的字符串有:112、1122、1122222、1123131231 ......

句号.:

匹配除换行符之外的任意一个字符。
比如:"112.",将匹配112+至少一个字符
可能匹配的字符串有:1121、1122、112abc、1123131231 ......,但不匹配112

插入符号^:

匹配一行的开始,但有时依赖于上下文环境,可能表示否定正则表达式中一个字符串的意思。
比如:“^abc”只匹配行首为abc的字符串

美元符$:

在一个正则表达式的末尾,匹配一行的结尾。
比如:"123$",将只能匹配到行尾为123的字符行,"^$"匹配匹配一个空行。

方括号[]:

匹配方括号内指定的字母集中的一个字符。
比如:"[abc]",将匹配字符a、b、c中的任意一个字符;而"[^abc]",将匹配除abc之外的所有字符。

反斜线符号\:

转义一个特殊的字符,使这个字符得到字面意义的解释。
比如:"\$",将表示它的原意"$";"\\",表示"\"。

转义尖括号<>:

用于标记单词边界。尖括号必须是转义的,否则它们只是字符的字面含义。
比如:"\<the\>"匹配"the",但不匹配"them","there"。

问号?:

匹配0个或1个前面的字符,用于匹配单个字符。
比如:"ab?c",将匹配"ac"或"abc"。

加号+:

匹配一个或多个前面的字符,它和星号*很相似,单它不匹配0个字符的情况。
比如:"ab+c"将匹配"abc","abbc","abbb...c"等。

转义波形括号{}:

指示匹配前面正则表达式的次数。波形括号必须是转义的,否则只有字符的字面含义。
比如:"[0-9]\{5\}"将匹配5位数字。

圆括号():

包含一组正则表达式。与"|"或expr操作符一起使用。

竖线|:

正则表达式的"或"操作符匹配一组可选的字符。

比如:"a(b|c)d"将匹配"abd"或"acd"。

正则表达式比较操作符:

[weblogic@etpmalldev6 logs]$ digit=132
[weblogic@etpmalldev6 logs]$ [[ $digit =~ [0-9] ]]
[weblogic@etpmalldev6 logs]$ echo $?
0

[weblogic@etpmalldev6 logs]$ digit="sfsfs"
[weblogic@etpmalldev6 logs]$ [[ $digit =~ [0-9] ]]
[weblogic@etpmalldev6 logs]$ echo $?
1

实例:

测试数据:

[weblogic@etp-mall-dev7][/tpdata/shell_script]$ cat list.txt 
1122
112
11222
2211
22111
1122222112
3131231112112

abdde
abede
bbcdefss
bbdde
the people's replublic of China
fafslk;kfak
fdoutjjlsjpwkfks
fasfsaFSAFSFSAF
FSAFSFAFFS
abdabeccde

查找包含字符串”112”且其后至少有一个字符的行:

[weblogic@etp-mall-dev7][/tpdata/shell_script]$ grep "112." list.txt
1122
11222
1122222112
3131231112112

查找字符”d”和”e”之间有一个任意字符的行:

[weblogic@etp-mall-dev7][/tpdata/shell_script]$ grep "d.e" list.txt 
abdde
bbdde

查找在字符”2”后有两个任意字符的行:

[weblogic@etp-mall-dev7][/tpdata/shell_script]$ grep "2.." list.txt 
11222
2211
22111
1122222112
3131231112112

查找/etc/passwd文件中root账号的信息,不使用插入符号^匹配:

[weblogic@etp-mall-dev7][/tpdata/shell_script]$ grep "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

查找/etc/passwd文件中root账号的信息,使用插入符号^匹配:

[weblogic@etp-mall-dev7][/tpdata/shell_script]$ grep "^root" /etc/passwd
root:x:0:0:root:/root:/bin/bash

查看有空行有多少行:

[weblogic@etp-mall-dev7][/tpdata/shell_script]$ grep "^$" list.txt | wc -l
1

查看所有匹配112*的行:

[weblogic@etp-mall-dev7][/tpdata/shell_script]$ grep "112*" list.txt 
1122
112
11222
2211
22111
1122222112
3131231112112

查看所有以数字”3”开头,”2”结尾的行:

[weblogic@etp-mall-dev7][/tpdata/shell_script]$ grep "\<3.*2\>" list.txt --color
3131231112112

查看文件中含有至少11个连续小写字母的行:

[weblogic@etp-mall-dev7][/tpdata/shell_script]$ grep "[a-z]\{8\}" list.txt 
bbcdefss
the people's replublic of China
fdoutjjlsjpwkfks
abdabeccde
^[0-9] +$ # 匹配数字
^[a-z0-9]+@[a-z0-9]+\.[a-z]+ # 匹配邮箱