Shell Script要点review
1.shell既是一种命令语言,又是一种程序设计语言
2.Batch批处理,写一个shell脚本,shell一次把这些命令执行完
3.解释执行,不需要编译,shell程序从脚本中一行一行的读取并执行这些命令
4.常见的shell脚本解释器有bash,sh,csh,ksh
5.bash是liunx默认的shell,sh是Unix默认的shell,bash完全兼容sh,sh写的脚本可以直接在bash中执行
6.编译型语言,C,C++,Java都是编译型语言,需要预先将写好的源代码转换成目标代码,称为编译,运行程序时候,直接读取目标代码,
由于目标代码非常接近底层,因此效率很高。但是运作于底层,处理的是字节,整数,浮点数或者其他机器层级的对象,所以实现一个简单的功能需要大量代码
7.解释型语言,脚本语言,解释器读取源代码并将其转换成目标代码,再由计算机运行,每次执行程序都多了编译过程,因此效率有所下降。awk,Python,Ruby,Shell
8.一个例子
#!/bin/bash
echo "hello world"```
其中#!表示这个脚本需要用什么解释器来执行,比如还有`#!/usr/bin/env python`
使用vim退出保存的时候,`:wq filename.sh`
####9.运行shell脚本
`chmod +x ./test.sh #使得脚本具有可执行权限`
`./test.sh #执行脚本`
或者直接运行解释器,参数是shell脚本的文件名,
`/bin/sh test.sh`
`bash test.sh`
####10.另外一个脚本,read的使用方法,read -p "comment"
!/bin/bash
Author: Kevin
echo "what is your name?"
read -p "please enter in your name: " PERSON
echo "hello,$PERSON"```
11.定义变量
variableName="value"#中间没有空格
12.使用变量
your_name="mozhiyan"
echo $your_name
echo ${your_name}#加上花括号是为了确定变量的边界
#比如这样
for skill in Ada Coffe Action Java
do
echo "i am good at ${skill}script"
done```
只有使用变量的时候才加美元符号。定义的时候,重新定义的时候都不需要
readonly将变量定义为只读变量
readonly variablename
使用unset删除变量
unset variable_name
三种变量类型
局部变量,仅在shell实例中有效,
环境变量,系统的环境变量
shell变量,shell程序设置的特殊变量
####13.一些特殊变量
$表示当前shell进程的ID,pid
echo $$
$0 表示当前脚本的文件名,也就是第0个参数
$n 传递给脚本函数的第几个参数
$# 表示传递给脚本函数的参数个数
$* 表示传递给脚本或者函数的所有参数,不加引号,分开输出,"$"会将所有参数作为整体输出
$@ 也是所有参数,分开输出,但是如果是这样 "$@" 会将参数分开输出
$? 表示上个命令的退出状态,或者函数的返回值
也就是说$@不论是什么情况,都会分开输出参数
但是$在普通情况下会分开输出,但是"$*"会整体输出```
14.shell替换
在双引号中使用变量就是一种替换,转义字符也是一种替换,表达式中含有特殊字符,也会替换
#!/bin/bash
a=10
echo -e "value of a is $a \n"```
使用-e参数表示对转义字符进行替换,如果不使用将原样输出
\\ \a 警报 \b退格 \f 换页 \n \r回车 \t 水平制表 \v 垂直制表
####15.命令替换
使用\`command\`或者$(command)
shell先执行命令,将输出结果暂时保存,在适当的地方输出
!/bin/bash
DATE=date
echo "Date is $DATE"
USERS=$(ls test.sh)#wc 显示文件的行数
echo "Logged in users are $USERS"
UP=date;uptime
echo "Uptime is $UP"```
16.变量替换
${var}变量本来的值
${var:-word}如果变量为空或被删除,返回word,不改变var的值,-后面的内容是作为字符串输出的,加上双引号会更好
${var:=word}如果变量为空或被删除,返回word,将var值设置为word
${var:+word}如果变量被定义,那么返回word,但是不改变var的值,没有定义,返回空值
${var:?message}如果变量为空或者被删除,那么将消息message送到标准错误输出,用来检测变量var是否可以被正常赋值,如果有值就输出这个值
17.shell运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,awk或者expr
expr可以完成表达式求值操作
#!/bin/bash
val=`expr 2 + 2`
echo "total value:$val"```
2 + 2之间必须要有空格,即表达式和运算符之间要有空格,如果没有就变成字符串打印2+2了
另外乘号*前面必须有反斜杠\才能实现乘法运算
条件表达式要在方括号之内,并且要有空格,[ $a == $b ],$a,$b与方括号之间也要有空格
==用于比较两个数字相等
关系运算符
-eq相等返回True,-ne不相等,-gt大于,-lt小于,-ge大于等于,-le小于等于
布尔运算符
-a 与运算,-o 或运算 !非运算
字符串运算符
=两个字符串相等,!=不相等,-z字符串长度为0,-n字符串长度不为0,str,[ $a ]字符串不为空
if [ -z $a ],if [ $a ]
文件测试运算符
用于检测文件的各种属性
####18.注释
使用#,而且没有多行注释,只能每一行加一个#号
如果需要将大段的代码注释起来,过一会取消注释,可以用花括号把这段代码括起来,定义成一个函数,然后没有地方调用这个函数,就起到注释的效果
####19.字符串
使用单引号
单引号里面所有特殊字符都无效,原样输出所有字符,并且也不出现转义字符,不能输出变量
str='this is a string'
使用双引号
双引号里面可以有变量,可以出现转义字符
拼接字符串
your_name="qinjx"
greeting="hello,"$your_name"!"
双引号将使用变量的表达式括起来只是起到不混淆的作用,也可以不用双引号
greeting_1="hello,${your_name}!"
echo $greeting$greeting_1```
获取字符串长度
echo ${#string}
提取子字符串,从0开始
echo ${string:1:4}
查找子字符串,is是要查的字符串,如果没有返回0,如果有,返回从1开始的index
echo \
expr index "$string" is` `
20.数组
bash支持一维数组,不支持多维数组,从0开始
定义数组
array_name=(value0 value1 value2)#使用空格将数组元素分割开
单独定义数组各个分量
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
#下标的范围没有限制,没有定义的元素的值就是空```
读取数组
${array_name[0]}
使用@或者*可以读取数组所有元素
${array_name[*]}
${array_name[#]}```
获取数组长度
#取得数组元素个数
length=${#array_name[@]}
length=${#array_name[*]}
#取得数组单个元素的长度
lengthe=${#array_name[n]}```
####21.echo命令
echo用于在屏幕上打印出指定的字符串
echo arg 或者 echo "arg" 默认都会作为字符串
显示转义字符
`echo "\"It is a test \""`
显示变量
name="OK"
echo "$name It is a test"```
如果变量与其他字符相连的话,使用大括号
mouth=9
echo ""$month"-1-2009"
echo "${month}-1-2009"
显示换行
echo "OK\n"
转义转义字符
echo -e "OK\n"
显示结果重定向至文件
echo "it is a test">myfile
原样输出字符串,使用单引号
echo '$name\"'
显示命令执行结果
echo \
date` `
22.printf命令
printf命令用于格式化输出,echo命令的增强,移植性比echo好
printf "Hello,shell\n"
echo会自动换行,printf必须显式添加换行符
printf format-string [arguments...]
以下例子
printf "%d %s\n" 1 "abc"
如果参数多于格式控制符的话,format-string可以重用,将所有参数都转换
printf %s abc def输出abcdef
如果没有arguments,%s用NULL代替,%d用0代替,arguments使用空格分隔,不用逗号。
printf "%f" 1.233
例子脚本
#!/bin/bash
#Author: Kevin
#Description: It's a script about the printf command practice
printf "%d %s\n" 1 "abc"
printf '%d %s\n' 1 "abc"
#舗o "" can be output too
printf %s avcdef
printf "%s\n" abc def
printf %s abc def
printf "%s %s %s\n" a b c d e f g h i j```
####23.if else语句
if ... fi
if .. else .. fi
if .. elif .. else .. fi
例子
if [ $a == $b ]
then
echo "a is equal to b"
fi```
$[2*3]这种方式可以直接计算出里面表达式的值
if test $[2*3] -eq $[1+5];then echo 'the two numbers are equal';fi;
同时if else语句也经常与test命令结合使用
test命令用于检查某个条件是否成立,与[]的作用是一样的
比如[ $a == $b ] 和 test $a == $b
#!/bin/bash
#Author: Kevin
#Description: It is a script about the ifelse expression
a=10
b=20
if [ $a == $b ]
then
echo "a is equal to b"
elif [ $a -gt $b ]
then
echo "a is greater than b"
elif [ $a -lt $b ]
then
echo "a is less than b"
else
echo "none if the condition met"
fi
if test $[2*3] -eq $[1+5];then echo "the two numbers are equal";fi;
num1=$[2*3]
num2=$[1+5]
if test $[num1] -eq $[num2]
then
echo "the two numbers are equal"
else
echo "the two numbers are not equal"
fi```
####24.case...esac语句
多分枝选择结构
case语句匹配一个值或者一个模式,匹配成功,执行相匹配的命令
case 值 in
模式1) command
;;
模式2) command
;;
*) command
;;
esac```
每一模式必须以右括号结束,取值可以是变量或者常数,所有命令开始执行至;;
如果无一匹配则使用星号捕获该值,再执行后面的命令
#!/bin/bash
#Author: Kevin
#Description: It is a script about the case ... esac statement
echo "Input a number between 1 to 4"
echo -e "your number is : \c"
read aNum
case $aNum in
1) echo "you select 1"
;;
2) echo "you select 2"
;;
3) echo "you select 3"
;;
4) echo "you select 4"
;;
*) echo "you do not select a number between 1 to 4"
;;
esac```
另一个例子
!/bin/bash
Author: Kevin
Description: It is a script about the case ... esac
options="${1}"
case $options in
-f) FILE="${2}"
echo "FILE name is $FILE"
;;
-d) DIR="${2}"
echo "Dir name is $DIR"
;;
*)
echo "basename ${0}
:usage:[-f file]|[-d directory]"
exit 1 #command to come out of the program with status 1
;;
esac```
basename输出最后一个文件名
使用"${1}"来将输入分隔开作为一个整体
25.for循环
for 变量 in 列表
do
command
done```
列表是一组值,数字,字符串,每个值通过空格分隔,每循环一次,就把列表中下一个值赋给变量
for loop in 1 2 3 4 5; do echo "the value is $loop"; done
`for str in "this is a string";do echo $str;done`
只有一个值,是this is a string
for file in ./*.sh;do echo $file;done
显示以sh结尾的所有文件
####26.while循环
while command
do
statements
done```
测试条件为真的时候执行
counter=0
while [ $counter -lt 5 ]
do
counter=`expr $counter + 1`
#counter=$[$counter+1]
#counter=$(expr $counter + 1)
echo $counter
done```
一个例子
!/bin/bash
Author: Kevin
Description: It is a script about while statement
counter=0
while [ $counter -lt 5 ]
do
counter=expr $counter + 1
echo $counter
done
echo "it's done"
counter=0
while [ $counter -le 10 ]
do
counter=$(expr $counter + 1)
echo $counter
done
echo "it's done"
while [ $counter -lt 20 ]
do
#这个[]表达式就是求值的,但是里面的元素$counter取变量值还是一样的
counter=$[$counter+1]
echo $counter
done```
另外一个while例子
#!/bin/bash
#Author: Kevin
#Description: a while statements expression
echo "type <ctrl+D> to terminate"
echo -n "enter your most liked film: "
while read Film
do
echo "yeah,great film the $Film"
done```
####27.until循环
until循环执行一系列命令直到条件为True时候停止
until command
do
statement
done```
command为条件表达式,返回值为false,继续执行循环体语句,否则跳出循环
一个例子
#!/bin/bash
#Author: Kevin
a=0
until [ ! $a -lt 10 ]
do
printf "%d\n" $a
a=$(expr $a + 1)
done```
####28.break
echo -n不换行输出
!/bin/bash
Author: Kevin
while :
do
echo -n "Input a number between 1 to 5:"
read aNum
case $aNum in
1|2|3|4|5) echo "your number is $aNum!"
;;
*) echo "you do not select a number between 1 to 5, game is over!"
break
;;
esac
done```
关注while:用法
break n表示跳出第n层循环
一个嵌套循环的例子
#!/bin/bash
#Author: Kevin
for var1 in 1 2 3
do
for var2 in 0 5
do
if [ $var1 -eq 2 -a $var2 == 0 ]
then
break 2
else
echo "$var1 $var2"
fi
done
done```
continue跳出当前循环
!/bin/bash
Author: Kevin
while :
do
echo -n "Input a number between 1 to 5:"
read aNum
case $aNum in
1|2|3|4|5) echo "your number is $aNum!"
;;
*) echo "you do not select a number between 1 to 5, game is over!"
continue
echo "game is over"
;;
esac
done```
按道理game is over不会出现,但是实际运行会运行到
continue后面跟一个数字,表示跳出第几层循环
29.函数
function_name(){
list of commands
[return value]
}```
如果不加return,最后一条命令运行结果作为返回值
shell 函数返回值只能是整数,表示函数执行成功与否,0表示成功
如果要让函数返回字符串,定义一个变量,用来接收函数的计算结果,然后脚本访问这个变量来获得函数返回值
调用函数只需要函数名,不需要加括号
函数返回值在调用该函数后通过$?来获得
一个例子
!/bin/bash
hello(){
echo "it's you"
}
hello```
另外一个例子
#!/bin/bash
funWithReturn(){
echo "the function is to get the sum of two numbers..."
echo -n "Input first number: "
read aNum
echo -n "Input another number: "
read anotherNum
echo "the two numbers are $aNum and $anotherNum !"
return $(($aNum+$anotherNum))
#return $[$aNum+$anotherNum]
}
funWithReturn
ret=$?
echo "the sum of two numbers is $ret !"```
另一个例子
函数嵌套
!/bin/bash
number_one(){
echo "i love you!"
number_two
}
number_two(){
echo "me too"
}
number_one```
删除函数
unset .f function_name
如果需要从终端调用函数,可以将函数定义在主目录下的.profile文件,这样每次登陆之后,在命令提示符后面输入函数名字就可以立即调用
30.函数参数
使用$n来获取参数的值,但是n>=10的时候就要使用${n}来获取参数了
$#参数个数,$*所有参数,$@所有参数,$?函数返回值
#!/bin/bash
funWithParam(){
echo "fisrt parameter is $1"
echo "third parameter is $3"
echo "tenth parameter is ${10}"
echo "eleventh parameter is ${11}"
echo "the amout of the parameter is $#"
echo "the string of the parameter is $*"
echo "another version of the all parameter is $@"
echo "all parameter \$* is "$*""
echo "all parameter \$@ is "$@""
}
funWithParam 1 2 3 4 5 6 7 8 9 10 11 12 14```
####31.输入输出重定向
命令输出可以是显示器,也可以是文件
command > file
并且输出重定向会覆盖文件内容
如果要追加,那么使用>>追加到文件末尾
echo line 2 >> users
ll > list
ls >> list
输入重定向
command < file
从文件中获取输入,本从键盘获取的输入命令会转移到文件读取内容
wc命令 -l 表示显示一个文件的行数,wc -c filename显示一个文件的字节数
wc -m filename显示一个文件的字符数 wc -w filename显示一个文件的字数
wc -l < list
每个linux命令运行时都会打开3个文件
标准输入文件stdin,文件描述符为0
标准输出文件stdout,文件描述符为1
标准错误文件stderr,文件描述符为2
command > file 将stdout重定向到file,command < file 将stdin 重定向为file
将stderr重定向到file,command 2 > file
追加到文件末尾,command 2 >> file
将stdout 和 stderr 合并后重定向到file
command > file 2>&1
或者
command >> file 2>&1
对stdin和stdout都重定向
command < file > file2
n>&m将输出文件m和n合并
n<&m将输入文件m和n合并
Here Document
嵌入文档,shell中特殊的重定向方式
command << delimiter
document
delimiter```
将两个delimiter之间的内容作为输入传递给command
wc -l << EOF
This is a simple lookup program
for good and bad restaurants
in cape town.
EOF```
/dev/null文件
如果希望执行某个命令,但是想丢弃输出结果,将输出重定向之/dev/null
command > /dev/null
如果要屏蔽stdout和stderr
command > /dev/null 2>&1
将stdout 和 stderr 合并后重定向到/dev/null
####32.文件包含
包含外部脚本,将外部脚本内容合并到当前脚本
. filename # .命令
source filename
被包含脚本不需要有执行权限
1.subscript.sh
url="www.baidu.com"```
2.main.sh
#!/bin/bash
. ./subscript.sh
echo $url```