Linux Shell
判断之前的 命令是否执行成功:
echo $?
linux中 执行文件方式的区别:
1、 sh 如: sh test.sh sh /user/file.sh 2、 ./ 使用这个方式 必须保证要执行的文件 有 可执行权限 如: ./test.sh ---这种主要是 . 做为执行声明, /表示当前目录 ./user/file.sh ---可以接绝对路径 3、直接使用shell 执行: 如一: /bin/sh test.sh /bin/sh /user/file.sh 如二: /bin/bash test.sh /bin/bash /user/file.sh
linux 文件权限管理:
关键字:chmod [ 选项 ] 文件名 选项: x 可执行 w 可写 r 可读 如: chmod +x test.sh 给文件 增加 执行权限 chmod -x test.sh 删除文件执行权限 chmod +xwr test.sh 给文件 增加 执行写入读取权限
linux变量的定义与引用:
PS: 1、命名是等号两边不能有空格 2、全局变量名 大写 查看系统变量: env 使用系统变量: echo $PATH #在终端打印path变量值 自定义变量: info="我是大佬" #定义 echo $info #使用 赋值的两种方式: 如一:info=$(pwd) #把pwd执行后的结果赋值给info echo $info #打印结果 如二: info=` pwd` #效果和上面一样, 注意 符号"``" 不是单引号,而是esc键下面的 echo $info 脚本中传参: $1 ~ $9: 匹配一位置参数传过来的 第一个 ~ 第九个 参数, 第九个以后通过 ${10} ~${n} 获取 $@ 匹配所有参数 $* 匹配所有参数 shift 默认删掉第一个位置参数 #a.sh 1 2 3 4 5 #/bin/bash echo $@ #输出为 1 2 3 4 5 shift echo $@ #输出为 2 3 4 5
linux 四则运算
加、减、乘、除
两种实现方式: 如一: expr PS:有两点限制 1、运算符两边需要空格 2、 乘号需要转义 expr 为 expression 的缩写 expr 10 + 3 #输出 13 expr 10+3 #输出 10+3 ***运算符两边需要空格*** expr 10 \\* 3 #输出 30 ***乘号需要转义*** expr 10 / 3 #输出 3 expr 10 - 7 #输出 3 如二: $[] echo $[10+3] #输出 13 echo $[10 + 3] #输出 13 符号两边 没有空格的限制 echo $[10*3] #输出 30 echo $[10/3] #输出 3 echo $[10-3] #输出 7
浮点型运算:
在shell中,做浮点运算一般是用bash的计算器 bc 在shell脚本中,一般我们的使用方法是: variable=$(echo "options; expression" | bc) 表达式讲解: options是bc的一些选项,例如: 可以通过scale去设置保留的小数位数。具体有哪些参数,可以man bc进行查看 expression就是我们具体的表达式,例如 10 * 3 " | " 这个符号,对于熟悉linux系统的人来说,这个再熟悉不过了。它叫做管道, 之所以会叫做管道,其实很形象,你可以把它看作一根水管,水管一头接入前一个命令的返回结果, 一头接入下一个命令。表示将前一个命令的执行结果作为后一个命令的参数输入。以上,表示将我们的表达式作为bc的参数输入。 如: #表示 10/3, 保留2位小数,将结果赋值给了num, 输出3.33 num=$(echo "scale=2; 10 / 3" | bc) echo $num
第二种:awk
如: num=$(awk 'BEGIN{print 7.01*5-4.01 }') #把结果赋值给变量 echo $num #打印结果 一般使用: msg=$(pwd | awk '{ print $1}') 将pwd的执行结果第一列 赋值给msg
linux if语句:
前言:
小提示:echo $? 判断上一次执行是否成功(成功返回 0 ,失败返回 1)
1、注意: shell 中 if语句与其他语言不通之处在于 shell中 if 后跟 命令,其他语言if语句 直接返回布尔值
2、在shell脚本的if其实是根据紧跟后面的那个命令的**退出状态码**来判断是否执行then后面的语句的。关于退出状态码,你只需要记住:正常退出(命令执行正常)的状态码是0, 非正常退出的状态码不是0(有少)。
3、以上语句的语义为: 如果if后面的命令执行正常(状态码0),那么就执行then后面的语句。否则不执行。 fi代表if语句的结束。
例 if - then : #这儿由于pwd是linux内置的命令,因此执行后会正常退出(状态码0),所以会执行then中的语句 #如果此处替换为一个不存在的命令(例如: pw),那么就会非正常退出,不会执行then中的语句 if pwd then echo 执行then里面的语句 fi #一定记得有结束语 例一简写: if pwd;then echo 执行then里面的语句 fi 例 if - then - else: 判断处理异常退出(状态码非0)情况 if pwd then echo 正常退出 else echo 非正常退出 fi 例 if - then - elif - else: if pwd then echo 正常退出 elif ls #条件 then echo 正常退出 else echo 非正常退出
test命令:
0、通过man test命令可以看到具体的用法。
1、test命令用于if-then或者if-then-else语句中,主要用于判断列出的条件是否成立,如果成立,就会退出并返回退出状态码0,否则返回非0。
2、test命令只能判断一下三类条件:
-
数值比较
-
字符串比较
-
文件比较
基本使用:
例一: 直接使用 test condition(条件) 例二:if - then if test condition then commands(命令) fi 例三: if - then - else if test codition then commands else commands fi
数值比较:
比较 | 描述 |
---|---|
n1 -eq n2 | 判断n1是否等于n2 |
n1 -ge n2 | 判断n1是否大于或等于n2 |
n1 -gt n2 | 判断n1是否大于n2 |
n1 -le n2 | 判断n1是否小于或等于n2 |
n1 -lt n2 | 判断n1是否小于n2 |
n1 -ne n2 | 判断n1是否不等于n2 |
字符串比较:
比较 | 描述 |
---|---|
str1 = str2 | 判断str1是否与str2相同 |
str1 != str2 | 判断str1是否与str2不相同 |
str1 < str2 | 判断str1是否比str2小(根据ASCII) |
str1 > str2 | 判断str1是否比str2大(根据ASCII) |
-n str1 | 判断str1的长度是否非0 |
-z str1 | 判断str1的长度是否为0 |
文件比较:
对于文件的比较,其实跟上面差不多,都是用test命令
case语句:
在使用if-then-else语句中,如果碰到条件很多的情况,如下: #!/bin/bash num=3 if (( $num == 1 )) then echo "num=1" elif (( $num == 2 )) then echo "num=2" elif (( $num == 3 )) then echo "num=3" elif (( $num == 4 )) then echo "num=4" fi 将以上代码替换为case: #!/bin/bash case $num in 1) echo "num=1";; 2) echo "num=2";; 3) echo "num=3";; 4) echo "num=4";; *) echo "defaul";; esac
linux 循环语句:
for-in语句:
如一: for i in a b c d do echo $i done #输出: a b c d 如二: for i in a,b,c,d do echo $i done #输出: a,b,c,d 造成这个上面结果的原因是:for...in循环默认是循环一组通过空格或制表符(tab键)或换行符(Enter键)分割的值。这个其实是由内部字段分隔符配置的,它是由系统环境变量IFS定义的。当然,既然是由环境变量定义的,那当然也就能修改啊。
修改IFS值:
如一: oldIFS=$IFS IFS=$"," for i in a,b,c,d do echo $i done #输出 a b c d 如二: for i in a b c d do echo $i done #输出 a b c d #还原IFS值: IFS=$oldIFS 以上第一个循环会分别输出abcde几个值。而第二个循环会输出a b c d e(即未处理)。因为我们把IFS的值设置为逗号了, 当然,不一定要是逗号,想设置什么,你说了算!
C语言风格的for
for ((i=0;i<=10;i++)) do echo $i done #输出 2 ... 10
while循环
在bash中的while语句,看起来似乎是结合了if-then语句和for循环语句。其基本格式如下:
while test command do other command done
与if-then语句一样,后面接test命令,如果test后面的命令的退出状态码为0. 那么就进入循环,执行do后面的逻辑。要注意在do后面的逻辑中写条件,避免死循环。
既然是接test命令,那么一切都可以参考if-then的test
如一: into=0 while test $into -lt 3 do echo $into into=$[$into + 1] #退出条件 done #输出 0 1 2 如二: into=0 while [ $into -lt 3 ] #注意:这里有个坑, 中括号两边 要有空格 do echo $into done #输出 0 1 2 如三: into=0 while (( $into <= 3 )) do echo $into done #输出 0 1 2 3
until语句:
until语句就是与while语句恰好相反, while语句是在test命令退出状态码为0的时候执行循环, 而until语句是在test命令退出状态码不为0的时候执行。
基本语法:
until test commands do other commands done
如: into=0 until test $into -lt 3 do echo $into into=$[$into + 1] done
其他两种 同while语句
break与continue控制循环
前言:
值得注意的是 break n 与 continue n 表示由内向外退出n层循环
break:
break用于跳出当前循环
如一: break跳出当前循环 #!/bin/bash for (( flag=0; flag <= 10; flag++ )) do if (( $flag == 5 )) then break fi echo $flag done 如二: break跳出内层循环 #!/bin/bash flag=0 while (( $flag < 10 )) do for (( innerFlag=0; innerFlag < 5; innerFlag++ )) do if (( $innerFlag == 2 )) then break fi echo "innerFlag=$innerFlag" done echo "outerFlag=$flag" done #会陷入死循环,输出 ... innerFlag=0 innerFlag=1 outerFlag=0 ... 如三: break用于跳出外层循环 #!/bin/bash flag=0 while (( $flag < 10 )) do for (( innerFlag=0; innerFlag < 5; innerFlag++ )) do if (( $innerFlag == 2 )) then #2表示外面一层循环,也就是终止了所有循环 break 2 fi echo "innerFlag=$innerFlag" done echo "outerFlag=$flag" done #输出 innerFlag=0 innerFlag=1
continue:
continue用于结束本次循环,进入下一次循环,注意,continue后面的语句不会执行。
如一: into=0 while test $into -lt 5 do if test $into -eq 3;then into=$[ $into + 1 ] contunue fi echo $into into=$[ $into + 1] done 如二: flag=0 while (( $flag <= 10 )) do if (( $flag == 5 )) then flag=$[$flag+1] continue fi echo "outerFlag=$flag" for (( innerFlag=11; innerFlag < 20; innerFlag++ )) do if (( $innerFlag == 16 )) then flag=$[$flag+1] continue 2 #这里2指定第2个封闭循环 fi echo "innerFlag=$innerFlag" done done
linux命令行---参数处理
前言:
shell可根据参数位置获取参数。通过 $1 到 $9 获取第1到第9个的命令行参数。$0为shell名。如果参数超过9个,那么就只能通过${}来获取了
例如: 获取第10个参数,
echo ${10}
如一: shell.sh 脚本内容 #!/bin/bash echo "第一个为文件名: $0 " # $0 获取的文件名会有 ./ 或者 完整路径 echo "第二个: $1 " echo "第三个: $2 " ....... 执行: ./shell.sh 第一个参数 第二个参数 PS: 通过basename命令来获取单纯的文件名$(basename $0) , 成功的得到文件名和命令行输入的参数(命令行参数以空格分隔,如果参数包含了空格,那么久必须添加引号了)
读取所有参数
第一种:通过 $# 可获取参数总数
如: #!/bin/bash for (( index=0; index<=$#; index++ )) do echo ${!index} done PS:由于${}内不能再写$符号,bash shell在这个地方是用了!符号,所以以上才写为了${!index}。
第二种:
在bash shell中还可以通过 $* 和 $@ 来获取所有参数
$* 会将命令行上提供的所有参数当作一个单词保存, 我们得到的值也就相当于是个字符串整体。 $@ 会将命令行上提供的所有参数当作同一字符串中的多个独立的单词。 #!/bin/bash #testinput.sh var1=$* var2=$@ echo "var1: $var1" echo "var2: $var2" countvar1=1 countvar2=1 for param in "$*" #第一种 do echo "first loop param$countvar1: $param" countvar1=$[ $countvar1 + 1 ] done echo "countvar1: $countvar1" for param in "$@" #第二种 do echo "second param$countvar2: $param" countvar2=$[ $countvar2 + 1 ] done echo "countvar2: $countvar2" 执行: ./testinput.sh 12 34 56 78 结果为: #第一种-------- var1: 12 34 56 78 var2: 12 34 56 78 param1: 12 34 56 78 #第二种--------------- countvar1: 2 param1: 12 param2: 34 param3: 56 param4: 78 countvar2: 5
获得用户输入:
通过read命令来实现与用户进行交互
#!/bin/bash
echo "输入你的name: "
read name
echo "你的name:$name"
运行上面代码会会显示“ 输入你的name: ” ,当输入后,会把输入的值赋值给name变量, 然后最终输出 “你的name: (你输入的内容)”。
PS:不指定read后面的变量名,如果我们不指定, read命令会将它收到的任何数据都放进特殊环境变量REPLY中
#!/bin/bash echo -n "yes or no(y/n)?" read echo "your choice: $REPLY" #注意大小写
多个输入
#!/bin/bash read -p "what's your name?" first last echo first: $first echo last: $last
以上示例首先输出“what's your name?”, 然后在本行等待用户输入(此处用read -p实现以上示例的echo -n + read命令的不换行效果),输入的参数以空格分隔,shell会把输入的值依次赋值给first和last两个变量。如果输入的值过多,假如我输入了3个值,那么shell会把剩下的值都赋值给最后一个变量(即第二三两个的值都会赋值给last变量)。
超时设置
通过read -t 来指定超时时间(单位为秒),如果用户在指定时间内没输入,那么read命令就会返回一个非0的状态码。
如: #/bin/bash if read -t 5 -p "Please enter your name: " name then echo "Hello $name" else echo "Sorry, timeout! " fi
运行以上示例,如果超过5秒没输入,那么就会执行else里面的。
linux三剑客:
前言:
grep、sed、awk 的查询条件均为 正则表达式 grep与find的区别在于,前者搜索文件中的内容,后者根据文件的属性 在系统中进行查找
grep:
前言:
-
grep 全面搜索正则表达式并把行打印出来
-
fgrep 它搜索字符串而不是搜索匹配表达式的模式。fgrep 命令使用快速的压缩算法。
$, *, [, |, (, )
和\
等字符串被 fgrep 命令按字面意思解释。这些字符并不解释为正则表达式语法: fgrep " 字符串" 文件名
-
pgrep 以名称为依据从运行进程队列中查找进程,并显示查找到的进程id。
语法: pgrep " 进程名 "
-
egrep 用于在文件内查找指定的字符串。egrep执行效果与
grep -E
相似,使用的语法及参数可参照grep指令,与grep的不同点在于解读字符串的方法。
语法:
grep 正则表达式 目标文件
如: grep xxxx a.txt #查找a.txt中是否有 xxxx,有责打印出来 grep '[a-z]' a.txt #查找包含有小写字母的 在a.txt中 grep '^abc' a.txt #查找以abc开头的 在a.txt中 grep 'abc$' a.txt #查找以abc结尾的 在a.txt中
sed:
Usage用法: sed [ option ] ' 条件指令' filename
option: 默认sed只是通过内存临时修改文件,源文件无影响
-
-i sed直接
修改
源文件, sed默认不修改 -
-i.bak 先
备份
,在修改文件内容 -
-n 取消默认输出, 一般与 p 结合使用
-
p 打印file的
行
,1p 为第一行,2p第二行.....一次类推 -
-s
替换
指定字符串 -
; 多条命令
分隔符
,比如:sed -n '1p;3p' book.txt #取book.txt中的第1和第3行(不连续) -
a 在某行后面
追加
一行内容 -
i 在某行前面
插入
一行内容 -
c 在原位置替换
-
g 获取内存缓冲区的内容,并替代当前模板块中文本
-
p 打印模板块的行
-
d 删除选择的行
-
! 非,取反
-
增
a (append) 追加
i (insert) 插入
-
在第二行
后面
追加内容 106,$lidao,UFO
sed '2a106,$lidao,UFO' a.md
-
在第四行
前面
插入 106,$lidao,UFO
sed '4i106,$lidao,UFO' a.md
-
在第二行
后面
追加多行内容 106,$lidao,UFO 107,$lhw,BYJM
sed '2a106,$lidao,UFO\n107,$lhw,BYJM' a.md
-
在第二行
前面
添加多行内容 106,$lidao,UFO 107,$lhw,BYJM
sed '2i106,$lidao,UFO\n107,$lhw,BYJM' a.md
-
把内容追加到
结尾
106,$lidao,UFO
sed '$a106,$lidao,UFO' a.md
删
-
删除单行内容
sed '1p/d' a.md
-
删除连续多行内容
sed '1,3p' a.md
-
删除不连续多行内容
sed '1p;3p' a.md
-
删除空行
sed /^$/d a.md
-
删除开头的空格
sed s/^' '*//g a.md
-
删除开头空格 与 空行
sed s/^' '*//g a.md |sed /^$/d
-
删除包含 tab键 与 空格的空行
sed -r '/^[ \t]*$/d' a.md -r 开启正则匹配
查
环境: cat >a.md <<"EOF" 101,$one,CEO 102,$haha,CTO 103,$hehe,COO 104,$heihei,CFO 105,$wawa,CIO EOF
-
取出第一行(单行)内容
sed -n ' 1p' a.md
-
取连续多行内容
sed -n '1, 3p' a.md
-
取出不连续多行
sed -n '1p;3p' a.md
-
找出文件包含heihei的行
sed -n '/heihei/p' a.md
-
显示从包含one的行到包含heihei的行
sed -n '/one/,/heihei/p' a.md
-
显示包含one的行和包含heihei的行
1、sed -n '/one/p;/heihei/p' a.md 2、sed -nr '/one|heihei/p' a.md
改
-
把文件中的数字修改为one
sed 's#[0-9]#one#g' a.md
sed 's#[0-9]#oldboy#g' sed.txt
-
把文件中的以103开头的行修改为one.com
1、sed 's/^103.*/one.com/g' a.md 2、sed '/^103/c one.com' a.md
-
把文件中的$字符替换为%
sed 's/\$/%/g' a.md sed 's#\$#%#g' a.md
-
取出a.md 的ip
cat a.md |sed -n '/IP/p'
awk: