欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Shell——语法

程序员文章站 2022-04-24 09:47:05
...

条件测试

1、测试命令:test和[,通过检查该类命令的退出码,决定条件测试是否成立

Shell——语法

shell认为退出码为0,测试条件成立;非0,测试条件不成立

2、测试类型

(1)整数:-eq、-ne、-lt、-gt、-le、-lt

  1 #!/bin/bash
  2 
  3 read myint
  4 test $myint -eq 100 #等于
  5 echo $?
  6 test $myint -ne 33  #不等
  7 echo $?
  8 test $myint -lt 35  #小于
  9 echo $?
 10 test $myint -gt 50 #大于
 11 echo $?
 12 test $myint -le 60 #小于等于
 13 echo $?
 14 test $myint -ge 66  #大于等于
 15 echo $?
 16 echo “\n”
 17 [ $myint -eq 100 ] #等于
 18 echo $?
 19 [ $myint -ne 33 ]  #不等
 20 echo $?
 21 [ $myint -lt 35 ]  #小于
 22 echo $?
 23 [ $myint -gt 50 ]  #大于
 24 echo $?
 25 [ $myint -le 60 ]  #小于等于
 26 echo $?
 27 [ $myint -ge 66 ]  #大于等于
 28 echo $?

Shell——语法

(2)字符串:==(=)、!=、-z、-n

  1 #!/bin/bash
  2 
  3 read mystring
  4 [ mystring == "hello" ] #相等
  5 echo $?
  6 [ mystring != "hello" ] #不等
  7 echo $?
  8 [ -z mystring ] #判断字符串是否为空串,是空串返回1
  9 echo $?
 10 [ -n mystring ] #判断字符串是否为空串,是空串返回0
 11 echo $?

Shell——语法

什么都不输入时,输入的是空串。空串比较必须:左右字符串都加“”、左右两侧都加X

(3)文件:-d、-f、-b、-c

Shell——语法

多条件测试

(1)逻辑非“!”

(2)逻辑与“-a”与 逻辑或“-o”用于连接两个测试条件

  1 #!/bin/bash
  2 
  3 #逻辑非
  4 [ ! "Xmystring" == "hello" ]
  5 echo $?
  6 
  7 printf "please your data1:"
  8 read d1
  9 printf "please your data2:"
 10 read d2
 11 #逻辑与
 12 [ $d1 -eq 100 -a $d2 -eq 200 ]
 13 echo $?
 14 
 15 #逻辑或
 16 [ $d1 -eq 100 -o $d2 -eq 200 ]
 17 echo $?

Shell——语法

if/then/elif/else/fi实现分支控制

如果将两条命令写在同一行中要用“;”号隔开;

命令和参数之间要用空格隔开;if执行的子命令为0(真),执行then后面的,否则执行else后面的。

[aaa@qq.com shell]# cat if.sh
#!/bin/bash

printf "please data:"
read data 

if [ $data -lt 100 ];then
	if [ $data -eq 50 ];then
		echo "data is eq 50"
	elif [ $data -gt 50 ];then
		echo "data is gt 50 and lt 100"
	else
		echo "data is lt 50"
	fi
else
	echo "data is gt 100"
fi
[aaa@qq.com shell]# /bin/bash if.sh
please data:43
data is lt 50
[aaa@qq.com shell]# /bin/bash if.sh
please data:50
data is eq 50
[aaa@qq.com shell]# /bin/bash if.sh
please data:67
data is gt 50 and lt 100
[aaa@qq.com shell]# /bin/bash if.sh
please data:104
data is gt 100

if的子命令除了“[”和“test”,还可以放其他的命令,只要其退出码为0或1

shell脚本中没有{}括号,所以用fi表示if语句块的结束

空代码块

在shell脚本中“:”是空命令,表示什么都不做

Shell——语法

||和&&

用于连接两个命令

&&:相当于if...then

||:相当于if not...then

Shell——语法

case/esac

相当于C语言中的switch....case,esac是case的结束标志,每个匹配分支可以有若干条命令但是末尾必须以“;;”结束,每个分支不需要break跳出

Shell——语法

循环语句

1、for循环

            类C                                                                                       for in循环

Shell——语法Shell——语法

for...in组合

  1 #!/bin/bash
  2 
  3 for i in {1..5}{a..e}
  4 do
  5     echo $i
  6 done

2、while 循环

[aaa@qq.com shel]$ vim while.sh
[aaa@qq.com shel]$ cat while.sh
#!/bin/bash

i=0
while [ $i -le 5 ]
do
	echo "hello $i"
	let i++
	#((i++))
done
[aaa@qq.com shel]$ /bin/bash while.sh
hello 0
hello 1
hello 2
hello 3
hello 4
hello 5

3、until循环:shell特有的

[aaa@qq.com shel]$ vim until.sh
[aaa@qq.com shel]$ cat until.sh
#!/bin/bash

i=0
until [ $i -ge 5 ]
do
	echo "hello $i"
	let i++
	#((i++))
done
[aaa@qq.com shel]$ /bin/bash until.sh
hello 0
hello 1
hello 2
hello 3
hello 4

4、死循环

  1 #!/bin/bash
  2 
  3 #方式一
  4 for (( ; ; ))
  5 do  
  6     echo "hello world!"
  7 done
  8 
  9 #方式二
 10 while :
 11 do
 12     echo "hello world"
 13 done
 14 
 15 while true
 16 do
 17     echo "hello world"
 18 done
 19 
 20 #方式三
 21 until false
 22 do
 23     echo "hello world"
 24 done

shell代码块内绝对不允许包含空语句,一般用“:”代替空语句

5、命令行循环

Shell——语法

【练习】求1—100的和

[aaa@qq.com shel]$ vim sum.sh
[aaa@qq.com shel]$ cat sum.sh
#!/bin/bash

i=1
sum=0
while [ $i -le 100 ]
do
	let sum+=i
	let i++
done
echo $sum
[aaa@qq.com shel]$ /bin/bash sum.sh
5050

显示“+”和求的数字和其和

[aaa@qq.com shel]$ vim sum.sh
[aaa@qq.com shel]$ cat sum.sh
#!/bin/bash

i=1
sum=0
str=''
while [ $i -le 100 ]
do
	let sum+=i
	if [ -z "$str" ];then
		str=$i
	else
		str=$str+$i
	fi
	let i++
done
echo $str=$sum
[aaa@qq.com shel]$ /bin/bash sum.sh
1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40+41+42+43+44+45+46+47+48+49+50+51+52+53+54+55+56+57+58+59+60+61+62+63+64+65+66+67+68+69+70+71+72+73+74+75+76+77+78+79+80+81+82+83+84+85+86+87+88+89+90+91+92+93+94+95+96+97+98+99+100=5050

求1—100之间的所有奇数的和

[aaa@qq.com shel]$ vim sum.sh
[aaa@qq.com shel]$ cat sum.sh
#!/bin/bash

i=1
sum=0
str=''
while [ $i -le 100 ]
do
	let sum+=i
	if [ -z "$str" ];then
		str=$i
	else
		str=$str+$i
	fi
	let i+=2
done
echo $str=$sum
[aaa@qq.com shel]$ /bin/bash sum.sh
1+3+5+7+9+11+13+15+17+19+21+23+25+27+29+31+33+35+37+39+41+43+45+47+49+51+53+55+57+59+61+63+65+67+69+71+73+75+77+79+81+83+85+87+89+91+93+95+97+99=2500

位置参数和特殊变量

  • $0、$1、$2...,称为位置参数,相当于C语言面main函数的argv[1],argv[2]...
  • $#:相当于C语言main函数的argc-1,注意这里的#不表示注释
  • aaa@qq.com:表示参数列表$1、$2
  • $?:上一条命令的退出状态
  • $$:当前shell的进程号

shift命令:位置参数可以用shift命令左移,不带参数的shift相当于shift 1

[aaa@qq.com shel]$ vim test.sh
[aaa@qq.com shel]$ cat test.sh
#!/bin/bash

echo "\$0->$0"
echo "\$1->$1"
echo "\$2->$2"
echo "\$3->$3"
echo "\$#->$#"
echo "\aaa@qq.com>aaa@qq.com"
echo "\$?->$?"
[aaa@qq.com shel]$ /bin/bash test.sh
$0->test.sh
$1->
$2->
$3->
$#->0
aaa@qq.com>
$?->0
[aaa@qq.com shel]$ /bin/bash test.sh arg1 arg2 arg3
$0->test.sh
$1->arg1
$2->arg2
$3->arg3
$#->3
aaa@qq.com>arg1 arg2 arg3
$?->0
[aaa@qq.com shel]$ vim test.sh
[aaa@qq.com shel]$ cat test.sh
#!/bin/bash

echo "----------shift 1 before---------"
echo "\$0->$0"
echo "\$1->$1"
echo "\$2->$2"
echo "\$3->$3"
echo "\$#->$#"
echo "\aaa@qq.com>aaa@qq.com"
echo "\$?->$?"

echo "----------shift 1 after---------"
shift 1
echo "\$0->$0"
echo "\$1->$1"
echo "\$2->$2"
echo "\$3->$3"
echo "\$#->$#"
echo "\aaa@qq.com>aaa@qq.com"
echo "\$?->$?"
[aaa@qq.com shel]$ /bin/bash test.sh arg1 arg2 arg3
----------shift 1 before---------
$0->test.sh
$1->arg1
$2->arg2
$3->arg3
$#->3
aaa@qq.com>arg1 arg2 arg3
$?->0
----------shift 1 after---------
$0->test.sh
$1->arg2
$2->arg3
$3->
$#->2
aaa@qq.com>arg2 arg3
$?->0

$0不移动,$1、$2移动一位,$3丢弃不要

遍历命令行参数

#!/bin/bash

#方式一
for i in aaa@qq.com
do
	echo $i
done

#方式2
while [ $# -ne 0 ]
do
	echo $1
	shift 1 #位置参数左移一位
done
[aaa@qq.com shel]$ /bin/bash bl.sh arg1 arg2 arg3 arg4

函数

shell中的函数没有返回值和参数列表,shell脚本中的函数必须先定义后使用

Shell——语法

1、函数传参:虽然shell函数没有参数,但是我们可以在调用函数时传任意多个参数,在函数内同样用$1、$2等变量来提取、$0并不会作为函数参数。改变函数中的位置参数不会影响函数外的变量。

  1 #!/bin/bash
  2 
  3 #注意:函数体的左花括号{和后面的命令之间必须有空格或换行
  4 function fun()
  5 {
  6     #在函数定义时并不执行函数体内的命令,调用的时候才执行
  7     echo "-----------------------"
  8     echo $0
  9     echo $1
 10     echo $2
 11     echo $3
 12     echo $#
 13     echo aaa@qq.com
 14     echo "function"
 15     echo "-----------------------"
 16 
 17 }
 18 #注意:最后一条命令和右花括号之间必须有换行或;
 19 
 20 
 21 fun argv1 argv2 argv3 #函数调用不写括号
 22 echo "--------shell----------"
 23 echo $0
 24 echo $1
 25 echo $2
 26 echo $3
 27 echo $#
 28 echo aaa@qq.com
 29 echo "-----------------------"

Shell——语法

2、函数返回值

(1)shell用$?来判定函数是否调用成功

Shell——语法

  • 函数调用或者返回时,将shell函数当命令
  • 通过命令的退出码来判定命令的执行结果是否正确
  • shell中if条件认为0为真,非0为假
  • [、test 都是命令

(2)echo方式只关心它的数据,而不关心函数的退出码($()这种方式的函数里有且只输出一个)

Shell——语法

shell脚本的调试方法

shell脚本的调试是通过选项来进行的

  • -n:读一遍脚本中的命令但不执行,用于检查脚本中的语法错误
  • -v:一边执行脚本,一边将执行过的脚本命令打印到标准错误输出
  • -x:提供跟踪执行信息,将执行的每一条命令和结果依次打印出来

这些选项的使用方法

  • 一是在命令行中提供参数
  • 二是在脚本开头提供参数
  • 三是在脚本中用set命令启用或禁用参数

数组

shell只支持一维数组,初始化时不需要定义数组的大小。数组的下标是从0开始,可以使用连续的,也可以使用不连续的,而且下标没有范围限制,下标可以是整数或算术表达式,其值大于等于0。利用下标来获取数组中的元素。

语法格式:

  3 #shell数组用括号表示
  4 array_name=(value1 value2 value3 value4 ... valuen)
  5 或
  6 array_name[0]=""
  7 array_name[1]=""
  8 array_name[2]=""
  9 array_name[3]=""
 10 array_name[10]=""


  3 arr=(1 2.32 'b' "string")
  4 
  5 ${arr[index]} #读取数组指定元素的值
  6 
  7 #获取数组中的所有的元素
  8 ${arr[@]}
  9 ${arr[*]}
 10 
 11 #获取数组的长度
 12 ${#arr[@]}
 13 ${#arr[*]}

 15 #遍历数组
 16 for (( i=0;i < ${#arr[*]};i++))
 17 do  
 18     echo "$i : ${arr[i]}"
 19 done
 20 for i in ${arr[*]}
 21 do
 22     echo $i
 23 done

shell与文件

1、输出重定向:“>”

Shell——语法

Shell——语法

2、追加重定向:“>>”

Shell——语法

3、输入重定向:“<”

Shell——语法

【练习】给file文件中的每一行都添加字符串“buy”

[aaa@qq.com file]$ cat file
hello 0
hello 1
hello 2
hello 3
hello 4
[aaa@qq.com file]$ cat test.sh
#!/bin/bash

while read line 
do
	echo 'buy '$line
done < file >> file_b
[aaa@qq.com file]$ /bin/bash test.sh
[aaa@qq.com file]$ ls
file  file_b  test.sh
[aaa@qq.com file]$ cat file_b
buy hello 0
buy hello 1
buy hello 2
buy hello 3
buy hello 4

默认情况下:

  • command > file 将stdout重定向到file,command < file 将stdin重定向到file
  • find a 2>file将stderr重定向到file,find zhu 2>>file将stderr追加到file(2表示标准错误文件stderr

Shell——语法

  • 将stdout和stderr合并后重定向到file
  1 $command > file 2>&1
  2 或
  3 $command >> file 2&1

4、Here Document:用来将输入重定向到一个交互式shell脚本或程序

基本形式:

  1 command << delimiter
  2     document
  3 delimiter

作用:是将两个delimiter之间的内容作为输入传递给command

  • 结尾的delimiter一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和tab缩进
  • 开始的delimiter前后的空格会被忽略掉

Shell——语法

5、/dev/null文件:是一个特殊的文件,写入到它的内容会被丢弃;如果尝试从该文件读取内容,那么什么也得不到;将命令的输出重定向到它,可以起到“禁止输出”的效果

屏蔽stdout和stderr:

Shell——语法

6、shell与信号

处理信号的方式:

  • trap 'commands' signal-list,当脚本收到signal-list清单内列出的信号时,trap命令执行引导中的命令
  • trap signal-list,trap不指定任何命令,接受信号的默认操作——结束进程的运行
  • trap "signal-list,trap命令指定一个空命令串,允许忽视信号

7、shell文件包含

  • .
  • source
[aaa@qq.com file]$ ll
total 8
-rw-rw-r--. 1 admin admin  50 Jul 17 06:32 api.sh
-rw-rw-r--. 1 admin admin 123 Jul 17 06:34 test.sh
[aaa@qq.com file]$ cat api.sh
function intadd()
{
	let data=$1+$2
	echo $data
}
[aaa@qq.com file]$ cat test.sh
#!/bin/bash

. api.sh
read d1 d2
ret=$(intadd $d1 $d2)
echo $ret

source api.sh
read d1 d2
res=$(intadd $d1 $d2)
echo $res
[aaa@qq.com file]$ /bin/bash test.sh
15 23
38
29 32
61

shell运算符

1、echo

格式:echo string

string可以加"",也可以不加

换行:\n

Shell——语法

不换行:\c

Shell——语法

2、printf:ping命令模仿C程序。printf使用引用文本或空格分隔的参数,外面可以在printf中使用格式化字符串,还可以指定字符串的宽度、左右对齐方式

printf命令的语法:printf format-string [arguments...]

【练习】产生一个随机数

Shell——语法

语法练习

1、编写进度条

  1 #!/bin/bash
  2 
  3 i=0
  4 bar=''
  5 label=("|" "/" "-" "\\")
  6 while [ $i -le 100 ]
  7 do
  8     printf "[\e[43;46;lm%-100s\e[0m][%d%%][%c]\r" "$bar" "$i" "${label[i%4]}"
  9     let i++
 10     bar=${bar}'#'
 11     sleep 0.1
 12 done
 13 printf "\n"

2、传入至少3个数,求最大值、最小值和平均值

  1 #!/bin/bash
  2 
  3 arr=(1 7 3 10 8 5 4 9 6 2)
  4 let min=${arr[0]}
  5 let max=${min}
  6 sum=0
  7 for (( i=0;i<${#arr[*]};i++))
  8 do
  9     [[ ${min} -gt ${arr[$i]} ]] && min=${arr[$i]}
 10     [[ ${max} -lt ${arr[$i]} ]] && max=${arr[$i]}
 11     let sum=sum+${arr[$i]}
 12 done
 13 echo $min
 14 echo $max
 15 echo $sum
 16 total=${#arr[*]}
 17 echo "$sum/$total" | bc

3、找规律并输出第100次会输出什么,0,1,1,2,3,5,8,13,21,34,55,89.........

 

4、反转文件