Shell编程
shell是命令解析器,是Unix操作系统的用户接口,程序从用户接口得到输入信息,shell将用户程序以及输入翻译成操作系统内核(kernel)能够识别的指令,并且操作系统内核执行完返回输出通过shell呈现给用户。
Shell也是一门编程语言,即Shell脚本。shell是一种解释执行的脚本语言,可以直接调用Linux命令。一个系统可以存在多个shell,可以通过cat /etc/shells命令查看系统中安装的Shell,不同的shell可能支持的命令语法是不同的。
操作系统内核(kernel)与shell是独立的套件,而且都可被替换;不同的操作系统使用不同的shell。
临时环境变量
所谓的临时变量是指在用户在当前登录环境生效的变量,用户登录系统后,直接在命令行上定义的环境变量便只能在当前的登录环境中使用#aaa=123 #$aaa 123
环境变量永久生效
/etc/profile 针对系统所有用户生效,此文件应用于所有用户每次登录系统时的环境变量定义。
$HOME/.bash_profile 针对特定的用户生效,$HOME为用户的宿主目录,当用户登录系统后首先继承/etc/profile文件中的定义,再应用$HOME/.bash_profile中的定义。
系统中预定义的环境变量
系统环境变量对所有用户有效,如:$PATH,$HOME,$PWD等。
一个shell脚本通常包含如下部分
首行:第一行内容在脚本的首行左侧,表示脚本将要调用的shell解析器,内容如下:
#!/bin/bash
#! 符号能够被内核识别成是一个脚本的开始,这一行必须位于脚本的首行,/bin/bash是bash程序的绝对路径,在这里表示后续的内容将通过bash解析执行。
注释:注释符号#需要放在每一行的开头。
内容:可执行内容和shell结构
Shell脚本的执行
1.输入脚本的绝对路径和相对路径
/root/helloWord.sh ./helloWord.sh
2.bash或sh+脚本
bash /root/helloWord.sh sh helloWord.sh 注:当脚本没有执行权的时候,root和所有者可以通过该方式执行脚本
3.在脚本前面加"." 或 source
source /root/helloWord.sh ../helloWord.sh
区别:第一种和第二种方式会新开一个bash,不同bash中的变量无法共享,但是使用../脚本.sh 这种方式会在同一个shell中执行。
shell中的变量:是shell中传递数据的一种方式,当shell中需要保存一些信息时,就保存到变量中。
变量设置规则:
1,变量名称可以由字母,数字和下划线组成,但是不能以数字开头,环境变量名建议大写,便于区分。
2,在bash中,变量的默认类型都是字符串型,如果要进行数值运算,则必须指定变量类型为数值型。
3,变量用等号连接值,等号左右两侧不能有空格。
4,变量的值如果有空格,需要使用单引号或者双引号包括。
变量的分类:自定义变量,系统变量,位置参数变量,预定义变量。
变量赋值:
1.定义赋值 A=9
2.将一个命令的执行结果赋值给另外一个变量 A=`ls -a` A=$(ls -la) aaa=$((4+5)) bb=`expr 4 + 5`
3.将一个变量赋给另一个变量 A=$STR cc="$aa"456 dd=${aa}789
单引号和双引号的效果不同,单引号中的内容会全部输出,双引号中的内容会发生改变。
位置参数变量
$n:n为数字,$0代表命令本身,$1-$9代表第一到第九个参数,十个以上的参数需要使用大括号包含。
$*:代表命令行中所有的参数,把所有的参数看成一个整体,以"$1 $2 $3 $4"的形式输出所有的参数。
$@:代表命令行中的所有参数,把每个参数区分对待,以"$1* $2*...$3*"的形式输出所有参数
$#:代表命令行中所有参数的个数,添加到shell的参数个数。
shift:参数左移;
预定义变量
$?:执行上一个命令的返回值,执行成功返回0,执行失败返回非0数;
$$:当前进程的进程号,即当前脚本生成的进程号。
$!:后台运行最后一个进程的进程号,最近被放入后台执行的进程。 把程序放在后台执行:命令+&
read命令
read [选项] 值
read -p(提示语句) -n(字符个数) -t(等待时间,单位为秒) -s(隐藏输入)
eg:read -t 30 -p "please input your name:" NAME
echo $NAME
read -s -p "please input your age:" AGE
echo $AGE
read -n 1 -p "please input your sex[M/F]" SEX
echo $SEX
运算符
格式:expr m + n 或$((m + n)) 注意:expr运算符中间要有空格
expr命令:对整数型变量进行算术运算
eg:expr 3 + 5
echo `expr 10 / 3`
echo `expr 3 \* 3`
sum=`expr \`expr 3 + 2\` \* 5 `
$(((3 + 2) * 5))
$()与${}的区别:$()的用途和反引号"一样,用来表示优先执行的命令;eg:echo $(ls a.txt) ${}就是取变量了;eg:echo ${PATH} $((运算内容))适用于数值运算;
条件判断 (test 或 [])
字符串测试:test str1 == str2 test str1 != str2 test -n str1 test -z str1
整数测试:test int1 -eq int2(==) test int1 -ge int2(>=) test int1 -gt int2(>) test int1 -le int2(<=) test int1 -lt int2(<) test int1 -ne int2(!=)
文件测试:test -d file 指定文件是否是目录
test -e file 文件是否存在
test -f file 指定文件是否是常规文件
test -L file 文件存在并且是一个符号连接
test -r file 指定文件是否可读
test -w file 指定文件是否可写
test -x file 指定文件是否可执行
多重条件测试:
条件1 -a 条件2 逻辑与 两个都成立则为真。
条件1 -o 条件2 逻辑或 两个只要有一个成立则为真
!条件 逻辑非 取反
eg: num=520
[ -n "$num" -a "$num" -ge 520 ] && marry you || echo go on
流程控制语句
if条件语句:
if [ 条件判断式 ]
then
程序
fi
或者
if [ 条件判断式 ] ; then
程序
fi
注意:if语句使用fi结尾,和一般语言使用大括号结尾不同;中括号和条件判断式之间必须有空格。then后面跟符号条件之后执行的程序,可以放在[]之后,用";"分隔,也可以换行写入,就不需要";"
多分支if条件语句:
if [ 条件判断式1 ]
then
当条件判断式1成立时,执行程序1
elif [ 条件判断式2 ]
then
当条件判断式2成立时,执行程序2
....省略更多条件
else
当所有条件都不成立时,最后执行此程序
fi
eg:
#!/bin/bash
read -p "please input your name:" NAME
#echo $NAME
if [ "$NAME" == root ]
then
echo "hello ${NAME}, welcome!"
elif [ $NAME == tom ]
then
echo "hello ${NAME}, welcome!"
else
echo "SB,get out here!"
fi
case命令:
case命令是一个多分支的if/else命令,case变量的值用来匹配value1,value2,value3等等。匹配到后则执行跟在后面的命令直到遇到双分号为止(;;)case命令以esac作为终止符。
格式:
CMD=$1
case $CMD in
start)
echo "starting"
;;
stop)
echo "stoping"
;;
*)
echo "Usage:{start|stop} "
esac
for循环:
第一种:
for N in 1 2 3
do
echo $N
done
或
for N in 1 2 3; do echo $N; done
或
for N in {1..3}; do echo $N; done
第二种:
for (( i=0; i <= 5; i++))
do
echo "welcome $i times"
done
或
for ((i=0; i <= 5; i++)); do echo "welcome $i times"; done
while循环
练习:求1-10各个数的平方和
num=1
while [ $num -le 10 ]
do
SUM=`expr $num \* $num`
echo $SUM
num=`expr $num + 1`
done
num=1
while [ $num -le 10 ]
do
sum=$(( $sum * $sum))
echo $sum
num=$(( $num + 1 ))
done
i=1
while(( i <= 10 ))
do
sum=$(( $i * $i ))
echo $sum
i=$(( $i + 1 ))
自定义函数
函数代表着一个或一组命令的集合,表示一个功能模块,常用于模块化编程。
说明:在shell中,函数必须先定义,再调用;使用return value来获取函数的返回值;函数在当前shell中执行,可以使用脚本中的变量。
格式:
函数名()
{
命令1...
命令2...
return 返回值变量
}
[ function ] funname [()]
{
action;
[return int;]
}
注意:如果函数名没有(),在函数名和{之间,必须要有空格以示区分。函数返回值,只能通过$?系统变量获得,可以显示加:return返回值,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)
脚本调试
sh -x scropt 这将执行该脚本并显示所有变量的值
在shell脚本里添加 set -x 对部分脚本调试
sh -n script 不执行脚本只是检查语法的模式,将返回所有语法错误。
sh -v script 执行并显示脚本内容
cut [选项] 文件名 默认分隔符是制表符
选项:-f 列号: 提取第几列
-d 分隔符: 按照指定分隔符分割列
eg:#cut -f 2 aa.txt 提取第二列
eg:#cut -d ":" -f 1,3 /etc/passwd 以:分割,提取第1和第3列
eg:#cat /etc/passwd | grep /bin/bash | grep -v root | cut -d ":" -f 1 获取所有可登录的普通用户和用户名
cut的局限性:不能分割空格(必须指定空格的个数,不够灵活)
awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
语法:awk '条件1 {动作1} 条件2 {动作2}...' 文件名
一般使用关系表达式作为条件:> >= <=等
动作:格式化输出,流程控制语句
eg:#df -h | awk '{print $1 "\t" $3}' 显示第一列和第三列
FS内置变量
eg:#cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN {FS=":"} {print $1 "\t" $3 }' 输出可登陆用户的用户名和UID,这里使用FS内置变量指定分隔符为:,而且使用BEGIN保证第一行也操作,因为awk命令会在读取第一行后再执行条件
指定分隔符还可以用-F更简单
eg:# cat /etc/passwd | grep "/bin/bash" | awk -F: '{print $1 "\t"$3 }' 效果同上
BEGIN 在所有数据读取之前执行
eg:#awk 'BEGIN {printf "first Line \n"} {printf $2 }' aa.txt 在输出之前使用BEGIN输出内容
END 在所有数据执行之后执行
eg:#awk 'END {printf "The End \n"} {print $2}' aa.txt 所有命令执行完后,输出一句"The End"
获取所有用户信息里的用户名:
cat /etc/passwd | awk -F: '{print $1}'
awk -F: '{print $1}' /etc/passwd
获取当前机器的ip地址:
# ifconfig eth0 | grep 'inet addr' | awk -F: '{print $2}' | awk '{print $1}'
sed:stream editor
s e d是一个非交互性文本流编辑器。它编辑文件或标准输入导出的文本拷贝。标准输入可 能是来自键盘、文件重定向、字符串或变量,或者是一个管道的文本。
注意: s e d 并不与初始化文件打交道, 它操作的只是一个拷贝,然后所有的改动如果没有重定向到一个文件,将输出到屏幕。
语法:sed [选项] ' [动作] ' 文件名
-n:使用安静模式。显示经过sed特殊处理的数据。
-e:允许多点编辑。
-i:直接修改读取的文档内容,而不是由屏幕输出。
a\:新增,a的后面可以接字串,在下一行出现
c\:替换
d:删除
i\:插入,i的后面可以接字串
p:打印
s:查找并替换,
eg:
sed '2p' sed.txt 显示第二行和所有数据
sed -n '2,3p' sed.txt 显示第二和第三行
df -h | sed -n '1p' 接收命令结果数据
sed '2a liuyifei' sed.txt 在第二行后面添加数据
sed '4i fengjie \
aaaaa' sed.txt 在第4行之前添加两行数据
sed '2c this is replace' sed.txt 替换第二行数据
sed 's/it/edu360/g' sed.txt 把sed.txt文件中的it替换为edu360,并输出
sed -e '1s/1/34/g;3s/yangmi//g' sed.txt 同时进行多个替换
sed -i '/s/it/edu360/g' sed.txt 想要真正的替换,需要使用-i参数。
定时器
crontab 命令允许用户提交、编辑或删除相应的作业。每一个用户都可以有一个crontab 文件来保存调度信息。可以使用它运行任意一个 shell 脚本或某个命令。
crontab命令格式
作用:用于生成cron进程所需要的crontab文件
crontab的命令格式
# crontab -e 使用编辑器编辑当前的crontab文件。
crontab文件格式
minute hour day-of-month month-of-year day-of-week commands
分< >时< >日< >月< >星期< >要运行的命令 < >表示空格
其中
Minute 一小时中的哪一分钟 [0~59]
hour 一天中的哪个小时 [0~23]
day-of-month 一月中的哪一天 [1~31]
month-of-year 一年中的哪一月 [1~12]
day-of-week 一周中的哪一天 [0~6] 0表示星期天
commands 执行的命令
书写注意事项
1,全都不能为空,必须填入,不知道的值使用通配符*表示任何时间
2,每个时间字段都可以指定多个值,不连续的值用,间隔,连续的值用-间隔。
3,命令应该给出绝对路径
4,用户必须具有运行所对应的命令或程序的权限
输入输出重定向
>:输出重定向,会替换
>>:输出重定向,不会替换,会累加。