您的位置:首页 > 运维架构 > Shell

shell笔记-全面总结-强化脚本编写能力

2016-11-12 14:33 344 查看
最近给双十一晚会做直播,并且双十一红包一角标广告形式投放出去,在预热阶段需要看下效果,数据团队没法给出一些指标数据,需要我们自己做数据分析给出,平时shell使用的少,很多数据分析的命令忘记了,趁此机会总结下:

shell文件头

需要定义解释器

#!/bin/bash


执行方式
第一种,作为程序执行:

chmod +x ./red-data.sh #给脚本添加执行权限


./
red-data.sh
#执行脚本


第二种,作为解释器参数执行:

/bin/sh
red-data.sh


变量

定义
shell中没有变量类型的概念,并且不需要提前声明,赋值=号左右不能有空格,如:

variableName="value"


如果shell中没有给变量赋值,则默认是空
调用变量
只需要在变量名字前加$即可调用,但是有时候为限定变量名的边界,需要大括号{}

site="youku"


echo $site

echo ${site}is
playing video


设置只读变量

site="youku"

readonly site


myUrl="tudou"


[root@a05.pre.ad.youku]$ site="tudou"
-bash: site: readonly variable

删除变量
使用unset删除变量,但是不能删除只读变量:

unset variable_name

特殊变量、参数
$0 shell中在$0中存放了脚本本身的名字,
$?
是显示最后命令的退出状态,
0
表示没有错误,其他表示有错误

$! shell把最后一个发送到后台进程的id
$$ 登录shell的进程id
$# 存放命令行中输入参数的个数,通常用来校验输入参数是否正确使用
$* 传递给程序的所有参数,在参数个数不确定时候,很有用
${n} 如果传递9个以上参数,不能用$10、$11来去参数,必须使用${10}、${11}
$@ 用法,$@要使用双引号括起来,否则和$*的用法相同了:
变量替换
${parameter:-value} 是如果parameter不为空就替换为它的值,为空就替换为value
${parameter:=value} 是parameter为空时,不但使用value,而且把它赋值给parameter(注意=),这种方法不能给位置参数赋值,parameter不能是数字
${parameter:?value} 是parameter不为空,shell就替换它的值,否则shell把value写入标准错误,然后退出(这种情况发生在登录shell中,不会冲系统注销)
${parameter:+value} 是如果parameter不为空就替换为value,否则什么也不替换

引用

单引号
单引号忽略所有特殊符号
双引号
部分特殊符号不被忽略
A)美元符号
B)反引号
B)反斜杠
双引号中用反斜杠去掉字符的特殊意义(美元符号、反斜杠、反引号、换行符、其它双引号),但是反斜杠在其它特殊符号前,双引号要把它忽略。

15:03 [root@a05.pre.ad.youku]$ echo "\ hello world \$y and \"$x\""
\ hello world $y and ""

第一个空格前的反斜杠没有被忽略,显示出来
反斜杠
续行、转义
反引号
告诉shell执行括起来的命令
$(...)结构
格式:$(command) 和反引号功能一样

14:59 [root@a05.pre.ad.youku]$ echo "there are $(who | wc -l) user login in"
there are 3 user login in

expr命令
expr只是整数计算,如果浮点型的计算,可以使用awk或bc计算
此命令支持的操作符有加(+)、减(-)、乘(*)、除(/)、求模(%),其中乘法*需要用反斜杠,因为linux中*会解析为当前目录下所有文件的名字

运算

算数运算
运算符说明举例
+加法`expr $a + $b` 结果为 30。
-减法`expr $a - $b` 结果为 10。
*乘法`expr $a \* $b` 结果为 200。
/除法`expr $b / $a` 结果为 2。
%取余`expr $b % $a` 结果为 0。
=赋值a=$b 将把变量 b 的值赋给 a。
==相等。用于比较两个数字,相同则返回 true。[ $a == $b ] 返回 false。
!=不相等。用于比较两个数字,不相同则返回 true。[ $a != $b ] 返回 true。
注意:乘法运算需要加反斜杠

关系运算
关系运算符只支持数字,不支持字符串,除非字符串的值是数字

关系运算符列表

运算符说明举例
-eq检测两个数是否相等,相等返回 true。[ $a -eq $b ] 返回 true。
-ne检测两个数是否相等,不相等返回 true。[ $a -ne $b ] 返回 true。
-gt检测左边的数是否大于右边的,如果是,则返回 true。[ $a -gt $b ] 返回 false。
-lt检测左边的数是否小于右边的,如果是,则返回 true。[ $a -lt $b ] 返回 true。
-ge检测左边的数是否大等于右边的,如果是,则返回 true。[ $a -ge $b ] 返回 false。
-le检测左边的数是否小于等于右边的,如果是,则返回 true。[ $a -le $b ] 返回 true。
布尔运算
运算符说明举例
!非运算,表达式为 true 则返回 false,否则返回 true。[ ! false ] 返回 true。
-o或运算,有一个表达式为 true 则返回 true。[ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a与运算,两个表达式都为 true 才返回 true。[ $a -lt 20 -a $b -gt 100 ] 返回 false。
字符串运算
运算符说明举例
=检测两个字符串是否相等,相等返回 true。[ $a = $b ] 返回 false。
!=检测两个字符串是否相等,不相等返回 true。[ $a != $b ] 返回 true。
-z检测字符串长度是否为0,为0返回 true。[ -z $a ] 返回 false。
-n检测字符串长度是否为0,不为0返回 true。[ -z $a ] 返回 true。
str检测字符串是否为空,不为空返回 true。[ $a ] 返回 true。
文件运算
用于检测Unix文件的各种属性
操作符说明举例
-b file检测文件是否是块设备文件,如果是,则返回 true。[ -b $file ] 返回 false。
-c file检测文件是否是字符设备文件,如果是,则返回 true。[ -b $file ] 返回 false。
-d file检测文件是否是目录,如果是,则返回 true。[ -d $file ] 返回 false。
-f file检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。[ -f $file ] 返回 true。
-g file检测文件是否设置了 SGID 位,如果是,则返回 true。[ -g $file ] 返回 false。
-k file检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。[ -k $file ] 返回 false。
-p file检测文件是否是具名管道,如果是,则返回 true。[ -p $file ] 返回 false。
-u file检测文件是否设置了 SUID 位,如果是,则返回 true。[ -u $file ] 返回 false。
-r file检测文件是否可读,如果是,则返回 true。[ -r $file ] 返回 true。
-w file检测文件是否可写,如果是,则返回 true。[ -w $file ] 返回 true。
-x file检测文件是否可执行,如果是,则返回 true。[ -x $file ] 返回 true。
-s file检测文件是否为空(文件大小是否大于0),不为空返回 true。[ -s $file ] 返回 true。
-e file检测文件(包括目录)是否存在,如果是,则返回 true。[ -e $file ] 返回 true。

控制流

if条件判断
主要有以下几种格式:
if ... fi 语句;
if ... else ... fi 语句;
if ... elif ... else ... fi 语句。
例如:

#!/bin/bash
echo "开始处理点播散投-----------"
if [ -n "$1" ]
then
dt=$1
else
dt=`date -d "1 day ago" "+%Y%m%d"`
fi
echo "正在查询日期:"${dt}

注意:[ expression ] expression与[]之间一定要有空格,否则语法错误

if ... else 语句也经常与 test 命令结合使用

#!/bin/bash
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

执行:

15:20 [root@a05.pre.ad.youku]$ sh test.sh
‘The two numbers are equal!‘

for循环
格式一:

for i in 1 2 3
do
echo $i
done

列出当前目录下所有文件

for file in *
do
echo $file
done

格式二:
不带参数的for循环,这种特殊格式,shell自动将命令行的所有参数注册列表

for var
do
command
......
done

相当于

for var in “$@”
do
command
......
done

while循环
只要while循环后的命令状态为0,循环就会一直执行下去
格式:

while command1
do
command
command
...
done

util命令
与while不同的是,只有util后的命令状态不为0,就会一直执行下去
格式:

util commond1
do
command
......
done

case逻辑
case可以将一个值与多个值比较
格式:

case value in
part1) command
......
command;;
........
partn) command
......
command;;
esac

把value依次与part1.....partn比较,发现匹配,则执行匹配项和双分号之间的所有命令,没有匹配则不执行。
例如:

#!/bin/bash

if [ "$#" -ne 1 ]
then
echo "用法:number数字"
exit 1
fi
case "$1"
in
0) echo zero;;
1) echo one;;
2) echo two;;
3) echo three;;
4) echo four;;
5) echo five;;
esac

case中还支持正则表达式匹配,例如万能匹配*

#!/bin/bash

if [ "$#" -ne 1 ]
then
echo "用法:number数字"
exit 1
fi

case "$1"
in
0) echo zero;;
1) echo one;;
2) echo two;;
3) echo three;;
4) echo four;;
5) echo five;;
*) echo "any thing"
esac

case的匹配条件可以使用 | 逻辑或
例如:

#!/bin/bash
if [ "$#" -eq 0 -o "$#" -gt 1 ]
then
hour=$(date +%H)
else
hour="$1"
fi

case $hour
in
0? | 1[01] ) echo "Good morning";;
1[2-7] ) echo "Good afternoon";;
* ) echo "Good evening";;
esac

break、continue
break和所有程序的意思是一样的,跳出所有循环,但break后边可以跟数字参数,标示跳出第几层循环,默认不写表示跳出本层循环
如:

break n


表示跳出第 n 层循环

#!/bin/bash
for var1 in 1 2 3
do
for var2 in 0 5
do
if [ $var1 -eq 2 -a $var2 -eq 0 ]
then
break 2
else
echo "$var1 $var2"
fi
done
done

执行结果:

15:42 [root@a05.pre.ad.youku]$ sh test-break.sh
1 0
1 5

continue 后面也可以跟一个数字,表示跳出第几层循环

字符串

拼接
shell中字符串拼接异常的简单,直接放到一起即可,如:

15:50 [root@a05.pre.ad.youku]$ echo "welcome to "$site
welcome to youku

获取长度

15:58 [root@a05.pre.ad.youku]$ site="youku"
tty:[0] jobs:[1] cwd:[/opt/flamegraph]
15:58 [root@a05.pre.ad.youku]$ echo ${#site}
5

截取

16:00 [root@a05.pre.ad.youku]$ site="youku"
tty:[0] jobs:[1] cwd:[/opt/flamegraph]
16:01 [root@a05.pre.ad.youku]$ echo ${site:1:3}
ouk

截取第1-3个字符

数组

shell中支持一维数组,使用和程序语言是一样的,下标也是从0开始计算index
定义格式:
空格分开

array_name=(value0 value1 value2 value3)


换行

array_name=(


value0

value1


value2

value3


)


也可以单独定义数组的各个分量:

array_name[0]=value0


array_name[1]=value1

array_name[2]=value2


读取

valuen=${array_name[2]}


使用@ 或 * 可以获取数组中的所有元素,例如:

${array_name[*]}


${array_name[@]}



获取长度
获取数组长度的方法与获取字符串长度的方法相同,例如:

# 取得数组元素的个数


length=${#array_name[@]}

# 或者


length=${#array_name[*]}


# 取得数组单个元素的长度


lengthn=${#array_name[n]}


注释

单行注释
使用# 注释

多行注释

方法一

: '
被注释的多行内容
'

方法二

:<<eof
被注释的多行内容
eof

方法三

:<<!
被注释的多行内容
!

方法四

if false ; then
被注释的多行内容
fi
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息