1、变量:(shell中大小写敏感)
1)变量定义
(1)变量定义和引用:(变量定义=的左右两边不能有空格)
a=1 引用变量:echo $a #1(echo命令向屏幕输出)
a=hello echo $a #hello
echo a #a
(2)如果内容有空格需要使用单引号或者双引号
a=hello world 报错:-bash: word: command not found
echo hello world #hello word
a='hello world' echo $a #hello world
a="hello world" echo $a #hello world
(3)单引号和双引号的区别(双引号支持转义,$开头的变量会被自动替换)
a="hello" echo 'abc $a' #abc $a 在单引号中$a会被当成字符串打印出来,没有办法直接引用变量
a="hello" echo "abc $a" #abc hello $a被引用出来了
注意:在bash中可以直接使用一个没有定义(不存在)的变量,但是这个变量什么也不会发生
2)变量的使用:
a="hello" echo $a_1 #什么也没输出
a="hello" echo $a _1 #hello _1
a="hello" echo ${a}_1 #hello_1
a="hello" echo "$a"_1 #hello_1
bash中变量的严谨使用方法:
echo ${a} \echo "$a"
3)预定义变量:
echo $PWD # 输出pwd命令的结果,pwd是一个看当前目录的命令, PWD是bash预先定义好的变量,将pwd命令的结果赋值给PWD这个变量
echo $USER
echo $HOME
echo $PATH #环境变量
4)数组变量:(使用()定义数组,使用空格分隔每个元素)
(1)数组的访问
数组在内存中是一块连续的地址
a=(1 2 3 4 5) echo $a #1 只打印出第一个元素
a=(1 2 3 4 5) echo ${a[2]} #3 打印出第三个元素
a=(1 2 3 4 5) echo ${a[-2]} 4 打印出倒数第二个元素
a=(1 2 3 4 5) echo ${a[*]} \echo ${a[@]} #1 2 3 4 5 打印出a数组中的所有元素
a=(1 2 3 4 5) echo ${#a[*]} \echo ${#a[@]} #5,前面加个“#”统计数组中的元素个数
(2)反引号:执行命令,把命令的返回值赋值给任何一个变量
b=`ls` (反引号,在键盘上数字1旁边的键上) echo $b #打印出ls命令的结果
c=(`ls`) #此时ls成为了一个数组, echo $c #只会打印出来ls命令结果的第一个元素
5)特殊符号的使用:
双引号:
单引号:
\反斜杠:转义,开启转义需要加-e参数 echo -e "a\nbb" #会把\n转义成换行
$(ls):与ls命令的结果一样
`反引号:用法特殊,代表命令的输出,echo my dir is `ls` #my dir is +ls命令的内容
$(()):对变量进行操作,$((a+b))\$((1+2+4*3))
(()):整数扩展,把里面的变量当作整数处理
((1...10)):等价于 seq 1 10
6)变量类型:
字符串:a="XXXX"
数字:i=1234
布尔:b=true
7)数字型变量操作:
注意:echo $? #查看上一句执行结果:0代表成功,非0代表失败
8)字符串的操作
s="hello from testerhome" echo ${s:6} #from testerhome,从第6为开始输出,空格也算
s="hello from testerhome" echo ${s:6:4} #from,从第6为开始输出4位
s="hello from testerhome" echo ${#s} #21,整个字符串长21个字符
s="hello from testerhome" echo ${s#hello} #from testerhome ,掐掉s字符串头部的hello
s="hello from testerhome" echo ${s#hel } #lo from testerhome
s="hello from testerhome" echo "${s#*o}" # from testerhome,匹配到o,并且把o及其前面的都去掉,空格保留
s="hello from testerhome" echo "${s#*m}" # testerhome,匹配到m,并且把m及其前面的都去掉,空格保留
s="hello from testerhome" echo ${s#*m} #testerhome,匹配到第一个m,并且把m及其前面的都去掉,空格不保留
s="hello from testerhome" echo "${s##*m}" #e ,贪婪匹配,匹配到最后m,并且把m及其前面的都去掉
s="hello from testerhome" echo "${s##*o}" #me ,贪婪匹配,匹配到最后o,并且把o及其前面的都去掉
s="hello from testerhome" echo ${s##*o} #me ,和上面一样
s="hello from testerhome" echo "${s%home}" #hello from tester ,去尾,去掉home
s="hello from testerhome" echo "${s%h*}" #hello from tester ,去尾,从后面开始匹配,第一个h及其后面的都去掉
s="hello from testerhome" echo "${s%%h*}" #什么也没有,贪婪匹配,两个h及其后面的都去掉
s="hello from testerhome" echo "${s%%o*}" #hell ,贪婪匹配到最前面的一个o
替换:
s="hello from testerhome" echo ${s/testerhome/aaa} #hello from aaa, testerhome被替换成aaa了
s="hello from testerhome" echo ${s/from/to} #hello to testerhome,
9)布尔变量:
true echo $? #0
false echo $? #1
10)算术判断:(所有算术运算要放在中括号中,中括号和表达式之间有空格,两边都有)
[ 2 -eq 2 ] ;echo $? #0,-eq相等
[ 3 -eq 2 ] ;echo $? #1,-eq相等
[ 2 -ne 2 ] 不等
[ 3 -gt 2 ] 大于
[ 3 -ge2 ] 大于等于
[ 2 -lt 3 ] 小于
[ 2 -le 2 ] 等于 小于
[ 3 -ge 2 -a 1 -ge 2] ;echo $? #1,-a逻辑与,也可以这样写[ 3 -ge 2 && 1 -ge 2]
[ 3 -ge 2 -o 1 -ge 2] ;echo $? #1,-o逻辑或,也可以这样写[ 3 -ge 2 || 1 -ge 2]
[ ! 2 -ge 1 ] ;echo $? #1,!逻辑非
(())也可以表示算术比较, ((8>=7));echo $? 0
类型判断:
-e file如果存在,返回为真 [ -e test ];echo $? #0
-f 如果是文件类型,返回为真 [ -f test ];echo $? #0
-d如果是目录类型,返回为真 [ -d test ];echo $? #0
。。。。。
2、逻辑控制
1)if语句
if [ condition ]; then ...; fi
if [ condition ]; then ...;else...;fi
if [ condition ]; then ...;elif....;fi
简单的逻辑可以用&&或者||代替(不等同if ...else)
[ -e test ]&&echo exist || echo not exist #exist ,[ -e test ]为真时执行输出exist,[ -e test ]为假时执行输出not exist,
[ -e test01 ] && echo exist || echo not exist #not exist,因为test01不存在
echo "1" && echo "2" || echo "3" && echo "4" || echo "5" || echo "6" && echo "7" && echo "8" || echo "9" #12478,前面执行成功了执行&&后面的表达式,前面执行失败执行||后面的表达式
1)for循环:
for ((c1;c2;c3));
do
...;
done
for((i=0;i<10;i++));do echo $i; done #1 2 3 4 5 6 7 8 9
array=(1 2 3 4 5); for((i=0;i<${#array[@]};i++)) do echo $i; done #1 2 3 4 5
array=(1 2 3 4 5); for x in ${array[@]};do echo $x;done #1 2 3 4 5
for x in `ls`;do echo $x;done #把ls命令输出的内容都输出
3)while循环
while [ $i -lt 3 ];do echo $i;((i++));done #0 1 2 ,-lt小于等于
while read x;do echo $x;done<(将3输入到前面的语句中)3 #abcde,前提,名字为3的文件中有内容为abcde
创建文件3写入内容abcde:1)vim 3 ;2)按键盘中的i字母 ,输入abcde ;3)按ESC键,输入:wq; 4)cat 3看3中的内容;)
echo "today is Tuesday">3 #将"today is Tuesday"输入到3这个文件中,(尖尖朝哪边就输出到哪边)
4)退出控制:
return
exit
break :
for f in *;do echo $f;if [ -d $f ];then break;fi;done #输出当前目录下的文件和第一个目录,当遇到第一个目录的时候就跳出循环;
continue:
for f in *;do echo $f;if [ -d $f ];then echo $f is file;else continue;fi;done #没搞明白,continue跳出当前循环,继续;
3、shell运行环境
1) bash命令会进入另一个shell环境, echo $$ #18123 ,echo $$查看当前进程的PID
2)a=000; (a=1;echo $a);echo $a # 1 000,()会进入子shell
3) a=000;{ a=1;echo $a;};echo $a # 1 1 {}表示当前shell
4)sleep 10& #&把(sleep 10)命令调入后台运行;bg 3 #进程调到后台执行 ; fg 3 进程调回前台执行; jobs查看后台进程
5)ps -ef #显示所有进程的PID的全格式;
6)$$,当前脚本的pid
6)shell环境变量(分系统环境变量和用户级环境变量)
(1)在/home/18871501/test目录下新建一个名为wulala.sh,输入内容echo "hello from testerhome"
(2)添加执行权限:chmod +x wulala.sh
(3)执行命令:bash wulala.sh #hello from testerhome
(4)返回上级目录(/home/18871501/)再次执行bash wulala.sh ,发现报错
(5)添加环境变量,通过ls -al查看.bash_profile文件,在.bash_profile文件环境变量:export PATH=$PATH:/home/18871501/test
(6)执行环境变量,让它生效:source ~/.bash_profile
(7)再次在/home/18871501/目录下执行
7)重定向
echo "hello from testerhome">1 ; cat 1 #hello from testerhome, >覆盖
echo "hello to testerhome" >>1;cat 1#hello from testerhome hello to testerhome,>>追加,不覆盖之前的内容
linux三剑客:grep\awk\sed
8)grep命令(文本搜索)
grep "hello" text.txt #hello from testerhome ,查找test.txt文件中查找hello
grep -i "hello" text.txt #hello from testerhome HELLO FROM TERSTERHOME,查找test.txt文件中查找hello,-i 不区分大小写
cat test.txt|grep -i "hello" #hello from testerhome HELLO FROM TERSTERHOME
cat test.txt|grep -o "hello" #hello,-o 只显示匹配的内容
cat test.txt|grep -io "hello" #hello HELLO
echo abcd |grep "c" # abcd
echo abcd |grep -o "c" # c
echo abcd |grep -o "c." #cd ,.正则表达式,代表c及c后面任何一个字符
echo abcdef |grep -o "c.*" #cdef,.正则表达式,代表c及c后面所有字符
curl命令(安装才能使用)
curl http://www.baidu.com #返回百度的源代码
curl http://www.baidu.com/s?wd=mp3 #
curl http://www.baidu.com/s?wd=mp3 | less ,pageDown翻页,一页一页的看,按啥结束?
curl -s http://www.baidu.com/s?wd=mp3 | grep "结果约" #一大堆
curl -s http://www.baidu.com/s?wd=mp3 | grep -o "结果约[0-9]" #结果约5
curl -s http://www.baidu.com/s?wd=mp3 | grep -o "结果约[0-9,]*" #结果约55,660,000
curl -s http://www.baidu.com/s?wd=mp3|grep -o "结果约[0-9,]*" |grep -o "[0-9,]*" #55,660,000
while read k;do echo $k;curl -s http://www.baidu.com/s?wd=$k;done<baidu.keyword |grep -o "结果约[0-9,]*" (baidu.keyword文档中有:mp3\mp4\android\ios几个字符串) #55,660,000 59,800,000 100,660,000 52,100,000
9)awk(通过分割符把字符串分割成不同的域(范围),通过$0、$1、$2把不同的域打印出来)
echo "123|456|789" |awk -F '|' '{print $1}' #123
echo "123|456|789" |awk -F '|' '{print $2}' #456
echo "123|456|789" |awk -F '|' '{print $2}' #789
echo "123|456|789" |awk -F '|' '{print $NF}' #789 $NF是awk命令分割的最后一个域
echo "123|456|789" |awk -F '|' '{print $10}' # 123|456|789
echo "123+456_789" |awk -F '+|_' '{print $1}' #123
echo "123+456_789" |awk -F '+|_' '{print $2}' #456
echo "123+456_789" |awk -F '+|_' '{print $3}' #789
echo "123+456_789" |awk -F '+|_' '{print $0}' #123+456_789 ,打印出则整个字符串
last -n 5|awk '{print $1}' #将last -n 5这个命令输出内容的第一列显示出来,awk命令默认使用空格做分割符的时候不用-F参数
cat passwd | awk -F ':' '{print $1}' #将passwd这个文件中的第一列分割出来
cat passwd |awk -F ':' '{print $1,$7}' #将passwd这个文件中的第一列,第七列分割出来,逗号默认显示成空格了
curl -s http://www.baidu.com/s?wd=mp3 |grep -o "结果约[0-9,]*" |awk -F '个|约' ‘{print $3}’ #52,100,000
10)sed(文本替换)
echo "cat dog fish cat"|sed 's/cat/wulala/' #wulala dog fish cat
echo "cat dog fish cat"|sed 's/cat/wulala/g' #wulala dog fish wulala,所有的cat都替换成wulala
echo "cat dog fish cat"|sed 's*cat*wulala*g' #wulala dog fish wulala,/可以替换成*或者其他符号
echo "123|456|789"|sed 's/|/+/g' #123+456+789
sed 's/hello/A/' test.txt #模式空间里面的内容被替换成功,原始文件并没有被替换
sed -i 's/hello/A/' test.txt #原始文件会被替换
sed -i.bak 's/hello/A/' test.txt #原始文件被替换,当前目录下生成一个test.txt.bak的备份文件,和没替换之前的原始文件一样
作业:统计testerhome社区帖子的点赞人数
a=`curl -s https://testerhome.com/topics|grep -o 'href="/topics/[0-9]*"'|awk -F '/|"' '{print $4}'`;for id in $a;do url='https://testerhome.com/topics/'$id;zan=`curl -s $url | grep -o -m1 '<span>[0-9]*' |awk -F '>' '{print $2}'`;if [ -n "$zan" ];then echo $url'点赞人数':$zan;else echo $url '点赞人数' 0;fi;done|awk -F '/' '{print $NF}'
11)begin和end
echo -e "1|2|3\n4|5|6\n7|8|9"
#输出结果如下,/n被转义成换行符
1|2|3
4|5|6
7|8|9
echo -e "1|2|3\n4|5|6\n7|8|9" | awk -F '|' 'BEGIN{a=0}{a=a+$2}END{print a}' #15,将第2列2、5、8加起来
$ echo -e "1|2|3\n4|5|6\n7|8|9" | awk -F '|' 'BEGIN{a=0}{print$2;a=a+$2}END{print a}' #2,5,8,15
python -m CGIHTTPServer启动临时服务
12)执行一个shell脚本
(1)vim test.sh ,在test.sh中写入内容保存推出
(2)直接执行bash test.sh
(3)加执行权限 chmod +x test.sh后,通过./test.sh执行
(4)加入环境变量后直接执行:test.sh
13)函数(shell默认传参只能传9个,参数超过9个需要加{})
1)格式
functionname() {
....
}
2)引用函数:直接写函数名:functionname
练习:输入两个数,对两个数做加减乘除运算:(shell的除法默认是整除,可以在shell脚本中使用awk来写除法)
(从键盘输入的命令:read -p "请输入:")
13)shell中内置了python