Shell脚本
一,规则:
1,等号左右两边不能有空格,调用变量需要在变量名前面加$
2,变量赋值常用的符号
1)双引号:允许引用其他的变量值
test=1
echo "这是变量test:$test"
2)单引号:禁止引用其他变量
test=2
echo "这不现实变量:$test"
3)反撇:将命令执行的结果赋值给变量
aaa=`echo "这是命令"`
4)read -p:接收用户输入内容赋值给变量使用
read -p "请输入内容" test
echo $test
5)字符串可以不加引号,应用变量的时候也可以不加引号
echo 这是一个字符串
3,变量的运算符(运算符左右之间需要加空格,不然就是字符串了,而且每个运算前面都需要加。 expr )
+:加
-:减
*:乘
/:除 expr $a \ $b * $a
4,流程控制语句(内容里面需要两头空格)
if [ command ];then
符合该条件执行的语句
elif [ command ];then
符合该条件执行的语句
else
符合该条件执行的语句
fi
4.1, 运算符 描述 示例
文件比较运算符:
-e filename 如果 filename 存在,则为真. [ -e /var/log/syslog ]
-d filename 如果 filename 为目录,则为真. [ -d /tmp/mydir ]
-f filename 如果 filename 为常规文件,则为真. [ -f /usr/bin/grep ]
-L filename 如果 filename 为符号链接,则为真 [ -L /usr/bin/grep ]
-r filename 如果 filename 可读,则为真 [ -r /var/log/syslog ]
-w filename 如果 filename 可写,则为真. [ -w /var/mytmp.txt ]
-x filename 如果 filename 可执行,则为真. [ -L /usr/bin/grep ]
filename1 -nt filename2 如果 filename1 比 filename2 新,则为真 [ /tmp/install/etc/services -nt /etc/services ]
filename1 -ot filename2 如果 filename1 比 filename2 旧,则为真 [ /boot/bzImage -ot arch/i386/boot/bzImage ]
字符串比较运算符 (请注意引号的使用,这是防止空格扰乱代码的好方法):
-z string 如果 string 长度为零,则为真 [ -z "$myvar" ]
-n string 如果 string 长度非零,则为真 [ -n "$myvar" ]
string1 = string2 如果 string1 与 string2 相同,则为真 [ "$myvar" = "one two three" ]
string1 != string2 如果 string1 与 string2 不同,则为真 [ "$myvar" != "one two three" ]
算术比较运算符
num1 -eq num2 等于 [ 3 -eq $mynum ]
num1 -ne num2 不等于 [ 3 -ne $mynum ]
num1 -lt num2 小于 [ 3 -lt $mynum ]
num1 -le num2 小于或等于 [ 3 -le $mynum ]
num1 -gt num2 大于 [ 3 -gt $mynum ]
num1 -ge num2 大于或等于 [ 3 -ge $mynum ]
4.2,测试命令
test命令用于检查某个条件是否成立,它可以进行数值、字符和文件3个方面的测试,其测试符和相应的功能分别如下。
(1)数值测试:
-eq 等于则为真。
-ne 不等于则为真。
-gt 大于则为真。
-ge 大于等于则为真。
-lt 小于则为真。
-le 小于等于则为真。
(2)字串测试:
= 等于则为真。
!= 不相等则为真。
-z字串 字串长度伪则为真。
-n字串 字串长度不伪则为真。
(3)文件测试:
-e文件名 如果文件存在则为真。
-r文件名 如果文件存在且可读则为真。
-w文件名 如果文件存在且可写则为真。
-x文件名 如果文件存在且可执行则为真。
-s文件名 如果文件存在且至少有一个字符则为真。
-d文件名 如果文件存在且为目录则为真。
-f文件名 如果文件存在且为普通文件则为真。
-c文件名 如果文件存在且为字符型特殊文件则为真。
-b文件名 如果文件存在且为块特殊文件则为真
举例:1)盘 /mnt是否是目录,是目录显示yes不是为空
test -d /mnt/ && echo "yes"
4.3, if [[ ]]和[ ]区别 || &&
(1)[]和test:两者是一样的,在命令行里test expr和[ expr ]的效果相同。
test的三个基本作用是判断文件、判断字符串、判断整数。支持使用 ”与或非“ 将表达式连接起来,test中可用的比较运算符只有==和!=
在[]中想进行比较实用><需要进行转义, 如果比较"ab"和"bc":[ ab \< bc ],结果为真,也就是返回状态为0.
(2)[[ ]]这是一个内置命令,支持通配符,逻辑组合等
字符串的模式匹配(使用=~操作符时甚至支持shell的正则表达 式)
逻辑组合可以不使用test的-a,-o而使用&& ||
举例:字符串比较时可以把右边的作为一个模式(这是右边的字符串不加双引号的情况下。如果右边的字符串加了双引号,则认为是一个文本字符串。),而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真。
总结:
用[[ ... ]]测试结构比用[ ... ]更能防止脚本里的许多逻辑错误。比如说,&&,||,<和>操作符能在一个[[]]测试里通过,但在[]结构会发生错误。
[[]]结构比Bash版本的[]更通用。在[[和]]之间的所有的字符都不会被文件扩展或是标记分割,但是会有参数引用和命令替换。
[[ ... ]]进行算术扩展,而[ ... ]不做
[[ ... && ... && ... ]] 和 [ ... -a ... -a ...] 不一样,[[ ]] 是逻辑短路操作,而 [ ] 不会进行逻辑短路
5,其他命令
(1)time 程序执行用的时间
(2)`date +%Y%m%d` 返回当天的时间戳(可以加符号):20150309
(3)last_date=`date -d last-day +%Y%m%d`: 昨天的时间20150308
(4),sleep 30 睡眠30秒(支持s,m,h)
二,应用
1,字符串切割
方法一: 利用shell 中 变量 的字符串替换
${parameter//pattern/string} 用string来替换parameter变量中所有匹配的pattern
string="hello,shell,split,test"
array=(${string//,/ }) #返回的列表
方法二: 设置分隔符,通过 IFS 变量
Shell 的环境变量分为 set, env 两种,其中 set 变量可以通过 export 工具导入到 env 变量中。其中,set 是显示设置shell变量,仅在本 shell 中有效;env 是显示设置用户环境变量 ,仅在当前会话中有效。换句话说,set 变量里包含了 env 变量,但 set 变量不一定都是 env 变量。这两种变量不同之处在于变量的作用域不同。显然,env 变量的作用域要大些,它可以在 subshell 中使用。
而 IFS 是一种 set 变量,当 shell 处理"命令替换"和"参数替换"时,shell 根据 IFS 的值,默认是 space, tab, newline 来拆解读入的变量,然后对特殊字符进行处理,最后重新组合赋值给该变量。
示例:
string="hello,shell,split,test"
#对IFS变量 进行替换处理
OLD_IFS="$IFS"
IFS=","
array=($string)
IFS="$OLD_IFS" # 返回列表
方法三: 利用tr 指令实现字符替换 (!只能针对单个分隔符)
由于只是对单个字符进行的替换,则可以用 echo args | tr "oldSpilt" "newSpilt" 的方式实现。
语法
tr(选项)(参数)
选项
-c或——complerment:取代所有不属于第一字符集的字符;
-d或——delete:删除所有属于第一字符集的字符;
-s或--squeeze-repeats:把连续重复的字符以单独一个字符表示;
-t或--truncate-set1:先删除第一字符集较第二字符集多出的字符。
参数
字符集1:指定要转换或删除的原字符集。当执行转换操作时,必须使用参数“字符集2”指定转换的目标字符集。但执行删除操作时,不需要参数“字符集2”;
字符集2:指定要转换成的目标字符集。
string="hello,shell,split,test"
array=(`echo $string | tr ',' ' '` )
2,数组
定义:使用declare -a 命令定义数组(数组的索引是从0开始计数的),接下来就可以通过[]操作符为不同索引位置的元素赋值。
declare -a names
names[0]=tom
names[1]=jack
定义并赋值
#定义的同时直接赋值
declare -a names=(tom jack)
#增加元素
names[2]=sue
# 直接定义list=(one two three)
取值:指定下标,使用[]操作符从数组中对应元素,然后使用$取值,格式:${数组名[索引]}
获得数组中所有值:${数组名[@]},${数组名[*]}
长度:利用”@”或“*”字符,将数组扩展成列表,然后使用”#”来获取数组元素的个数。
echo "数组days的元素个数为:${#days[@]}"
echo "数组names的元素个数为:${#names[*]}"
遍历
(1)${数组名[@]}、${数组名[@]}均可以获得所有元素(不管是元素列表,还是一整个字符串),使用for循环遍历即可
for day in ${days[*]} #或${days[@]}
do
echo $day
done
(2)带数组下标的遍历,当需要使用到数组的下标时,可以使用${!数组名[@]}
for i in ${!days[@]}
do
echo ${days[$i]}
done
(3)while循环:根据元素的个数遍历,但对于稀疏数组,可能会丢失数据
names=() #数组names是一个稀疏数组
names[1]=tom
names[2]=jack
i=0
while [ $i -lt ${#names[*]} ]
do
echo ${names[$i]}
let i++
done
删除:删除一个数组或数组中元素用unset命令。
unset 数组名[索引] #删除索引下的元素
unset 数组名 #删除整个数组
连接:用()将多个数组连接在一起,()中各个数组用空格隔开。
days=(one two three four)
names=(tom jack)
days=(${days[@]} ${names[@]})
三,高级
一.正则表达式
1.正则表达式的作用和组成
1)正则表达式的作用
按照规则对文本数据进行过滤处理
帮助用户快速查找文本内容
2)正则表达式的组成
普通字符串
大写字母A-Z
小写字母a-z
符号
元字符
2.正则表达式的常见选项和应用
1)正则表达式常见的选项
-n:显示行号
-0:显示匹配内容
-i:不区分大小写
-vn:取反
2)正则表达式常见的元字符
^:起始内容
$:结束内容
.:匹配任意单个字符
[]:匹配括号中的内容
[-]:匹配括号里边内容的范围
{n}:匹配范围的次数
{n1-n2}:匹配开始和结束内容
[^]:匹配括号之外的任意字符
:转义字符
3.grep的应用
1)过滤关键字中包换the的并且显示行号
grep -n "the" test.txt
2)查找开头是the的行
grep -n "^the" test.txt
3)匹配任意单个字符开头是w中间任意结束为d的关键字
grep -n "w..d" test.txt
4)匹配括号里边的内容(任意一个)
grep -n "sh[io]rt" test.txt
5)只显示匹配内容
grep -o "wood" test.txt
4.扩展正则表达式
1)扩展正则表达式常见的选项
+:重复一个或者一个以上的前一个字符
?:显示当前字母前的一个字符
|:或者,多出多个字符
():查找组字符串
()+:辨别多个重复的组
二,sed的作用和工作流程
1,sed的作用
sed是一个文本文件解释转换工具,用于读取,修改,显示配置文件数据
2,sed处理数据的流程
读取:从文件,输入,管道命令读取数据,临时储存读取的数据
执行:根据sed命令在模式操作空间中进行无交互修改数据
显示:将文本文件的修改结果显示给用户
3,sed命令常见选项操作符
3.1,sed命令常见的选项
-n:显示处理后的结果
-h:显示帮助
-e:指定使用脚本或者命令处理文本数据
-f:指定脚本处理输入的文本数据
-i:直接编辑文本文件
3.2,sed常见的操作符
a:添加内容
d:删除内容
p:打印内容
s:替换内容
y:字符转换
c:将指定行替换成指定内容
i:向匹配行插入指定内容
4.sed的应用
4.1.显示1到5行的数据
sed -n '1,5p' test.txt
4.2.显示奇数行
sed -n -e '1p;3p;5p' test.txt
4.3.删除第一行数据
sed '1d' test.txt
4.4.将大写Linux替换成小写
sed -i 's/Liunx/liunx' test.txt
4.5.对ip关键字添加注释、
sed -i '/^ip/s^/#/' test.txt
4.6.将1~5行数据迁移到37行后
sed -i '1,5{H;d};20G' test.txt
三,awk
1,awk的作用
读取文本数据根据需要过滤关键内容
2,awk的变量
FS:文本字段分隔符
NF:处理行数
NR:处理数据的行号
$0:处理整行数据
$n:处理数据行的第几列数据
3,awk的基本应用
3.1,awk显示文本中的内容
awk '{print}' test.txt
3.2,显示第一列数据
awk '{print $1}' test.txt
3.3.显示第一列和第二列数据
awk '{print $1,$2}' test.txt
3.4.显示第一列和第二列数据使用–号分割
awk '{print $1"———"$2}' test.txt
3.5.显示第一行和第二行数据
awk 'NR==1,NR==2{print}' test.txt
3.6.过滤/etc/passwd的第七列数据
awk -F ':' {'print $7'} /etc/passwd
4,应用
4.1,Ubuntu 开机自启内容
1,移动test.sh文件到/etc/init.d目录下
mv test.sh /etc/init.d/
2,给文件增加权限
chmod +750 test.sh
3,设置开机自动启动
update-rc.d test.sh defaults
4.这样一个开机自动化脚本就完成咯
5,报错解决
1,shell脚本中报binary operator expected错
这块if [ -z $1 ]; then中的获取变量,使用双引号引起来就好了!示范:if [ -z “$1” ]; then