shell编程
Posted pier~呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell编程相关的知识,希望对你有一定的参考价值。
shell编程
概述
Shell是一个命令行解释器,它接收应用程序/用户命令,然后调用操作系统内核
Shell还是一个功能相当强大的编程语言,易编写、易调试、灵活性强。
注:Centos默认解析器时bash
shell脚本入门
#!/root/bash
echo "hello Word!!"
执行:
- **方式一:**采用bash或sh+脚本的相对路径或绝对路径(不用赋予脚本+x权限)
- **方式二:**采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x)
变量
-
系统变量:使用工具查看所属位置
H O M E 、 HOME、 HOME、PWD、 S H E L L 、 SHELL、 SHELL、USER等
-
自定义变量
-
定义变量 变量名=变量值。注:定义变量不能有空格,做特殊处理,一切皆字符串
-
撤销变量 unset 变量名
-
静态变量 readonly D=10 注:不能直接更改,也不能直接撤销,除非直接重新加载
-
变量如果有空格,需要使用单引号或双引号
-
提升全局变量,使用export,可以让其他shell使用
[root@pier shells]# export B [root@pier shells]# ./helloworld.sh helloworld 10
-
变量规则: 和Java类似 环境变量名建议大写
单引号双引号,基本上类似于编程语言中的引用字符串
区别在于单引号’ '内剥夺所有字符的特殊含义,所有字符都是单纯的字符串而没有特殊功能,比如$取参数等命令都是无效的
而双引号" "中除了字符串,特殊字符是没有被转义的,$等特殊字符一样可以使用其功能。
反引号``是命令替换,通常用于把命令输出结果传给入变量中,类似变量后$=(命令)如:
-
-
特殊变量
- $n (功能描述,n为数字,%0代表该脚本名称,$1-
9
代
表
第
一
到
第
九
个
参
数
,
十
以
上
的
参
数
需
要
用
大
括
号
包
含
,
如
9代表第一到第九个参数,十以上的参数需要用大括号包含,如
9代表第一到第九个参数,十以上的参数需要用大括号包含,如10)
- 例:
vim param.sh
- 例:
#!/bin/bash echo '=============$n============' echo $0 echo $1 echo $2 :wq
执行
[root@pier shells]# ./param.sh a b =============$n============ ./param.sh a b
- $# 打印执行脚本时传入变量的个数
- $* / $@ 打印传入变量
- $? 判断上一次命令是否正确0为true 非0为false
- $n (功能描述,n为数字,%0代表该脚本名称,$1-
9
代
表
第
一
到
第
九
个
参
数
,
十
以
上
的
参
数
需
要
用
大
括
号
包
含
,
如
9代表第一到第九个参数,十以上的参数需要用大括号包含,如
9代表第一到第九个参数,十以上的参数需要用大括号包含,如10)
运算符
加上(())或者[]就可以正常运行了
条件判断
基础语法
-
test condition
[ condition ](注意判别式前后一定要有空格)
常用判断条件
- 1、两个整数之间的判断
比较 | 符号 | 来源记忆 |
---|---|---|
大于 | -gt | greater than |
大于等于 | -ge | grreater equal |
小于 | -lt | less than |
小于等于 | -le | less equal |
等于 | -eq | equal |
不等于 | -ne | not equal |
实操:
判断2和3的大小:
[root@pier shells]# [ 2 -gt 3 ]
[root@pier shells]# echo $?
1
[root@pier shells]# [ 2 -lt 3 ]
[root@pier shells]# echo $?
0
- 2、字符串之间的比较
- ==
实操,判断字符串s="== n = = " 和 s 1 = ′ = = n=="和s1='== n=="和s1=′==n=='是否一致
[root@pier shells]# s="==$n=="
[root@pier shells]# s1='==$n=='
[root@pier shells]# [ s1==s ]
[root@pier shells]# echo $?
0
[root@pier shells]# echo '==$n=='
==$n==
[root@pier shells]# echo "==$n=="
====
这里就让我不解了,于是,我们找找为什么会出现相同的呢?
我貌似有一点点的傻,这个参数,在赋值的时候,仅仅是一个字符串,我们在判断的时候,也只是判断这两个字符串是否一样,二并没有去执行,因此,在下面的echo输出结果不一致,二在比较s和s1两个字符串是判断为正确。
- 3、按照文件权限进行判断
- -r 有读的权限(read)
- -w 有写的权限(write)
- -x 有执行的权限 (execute)
实操:
[root@pier shells]# test -x 200
[root@pier shells]# echo $?
1
[root@pier shells]# ll
总用量 8
-rw-r--r--. 1 root root 0 12月 17 10:39 200
- 4、按照文件类型进行判断
- -f文件存在并且是一个常见的文件(file)
- -e 文件存在(existence)
- -d 文件存在并且是一个目录(directory)
实操:判断文件abc是否存在,abd呢?
[root@pier shells]# [ -e abc ]
[root@pier shells]# echo $?
0
[root@pier shells]# ll
总用量 8
-rw-r--r--. 1 root root 0 12月 17 10:39 200
drwxr-xr-x. 2 root root 6 12月 17 15:20 abc
-rwxr--r--. 1 root root 40 12月 17 09:40 helloworld.sh
-rwxrwxr--. 1 root root 151 12月 17 10:29 param.sh
[root@pier shells]# [ -e abd ]
[root@pier shells]# echo $?
1
- 5、多重判断
- || && 运算,和Java类似
实操:
[root@pier shells]# [ 100 -lt 200 ] && [ 100 -gt 50 ]
[root@pier shells]# echo $?
0
[root@pier shells]# [ 100 -lt 200 ] && [ 100 -lt 50 ]
[root@pier shells]# echo $?
1
[root@pier shells]# [ 100 -gt 200 ] && [ 100 -gt 50 ]
[root@pier shells]# echo $?
1
[root@pier shells]# [ 100 -gt 200 ] && [ 100 -gt 50 ]
[root@pier shells]# echo $?
1
[root@pier shells]# [ 100 -gt 200 ] || [ 100 -gt 50 ]
[root@pier shells]# echo $?
0
流程控制
流程控制的作用:
继续运行位在不同位置的一段指令(无条件分支指令)。
若特定条件成立时,运行一段指令,例如C语言的switch指令,是一种有条件分支指令。
运行一段指令若干次,直到特定条件成立为止,例如C语言的for指令,仍然可视为一种有条件分支指令。
运行位于不同位置的一段指令,但完成后会继续运行原来要运行的指令,包括子程序、协程(coroutine)及延续性(continuation)。
停止程序,不运行任何指令(无条件的终止)。
if判断
基本语法
#!/bin/bash
if [ condition1 ]#这是开始语句
then
语句1
elif [ condition2 ]
then
语句2
·
·
·
else
echo 语句n
fi#这是结束语句的标志
实例:
#!/bin/bash
#if测试脚本
if [ $1 -eq 1 ]
then
echo "大数据,我来了!!!"
elif [ $1 -eq 2 ]
then
echo "大数据,pier又回归!!!"
else
echo "都不留爷,pier要离开了!"
fi
执行:
[root@pier shells]# ./if.sh 2
大数据,pier又回归!!!
[root@pier shells]# vim if.sh
[root@pier shells]# ./if.sh 2
大数据,pier又回归!!!
[root@pier shells]# ./if.sh 1
大数据,我来了!!!
[root@pier shells]# ./if.sh 3
都不留爷,pier要离开了!
[root@pier shells]# ./if.sh
./if.sh: 第 3 行:[: -eq: 期待一元表达式
./if.sh: 第 6 行:[: -eq: 期待一元表达式
都不留爷,pier要离开了!
这里我们发现这个他居然有错误提示,于是发现了,报错的两行正好是我们需要传入参数的两行,所以,我们就可以在if判断外边再加一个判断参数不为空的函数就可以了。
if [ $# -lt 1 ]
then
echo "请传参!"
exit
fi
case分支
#!/bin/bash
case $1 in
"1")
echo "这是1分支! ! !"
;;#这个相当于break
"2")
echo "这是2分支!!!"
;;
echo "default结束了!!!"
;;
esac
for 循环
for(( 初始值;循环控制条件;变量变化 ))
do
程序语句
done
注:在循环控制条件中使用><=这类符号,不识别-gt这类符号
注意点$@和$*的的区别:在打印时,不加双引号时都是循环调用,主要是注意在在输出"$*"时。是一次性拿进来所有的参数,而其他的情况,都是一次只拿一个参数。循环调用。
[root@pier shells]# ./for1.sh 刘亦菲 小阿七 Gai
==输出不加引号的$*==
你好美女--刘亦菲
你好美女--小阿七
你好美女--Gai
==输出不加引号的$@==
你好美女--刘亦菲
你好美女--小阿七
你好美女--Gai
==输出加引号的$*==
你好美女--刘亦菲 小阿七 Gai
==输出加引号的$@==
你好美女--刘亦菲
你好美女--小阿七
你好美女--Gai
while
while [ 条件判断式 ]
do
程序
done
read读取控制台输入
read(选项)(参数)
选项:
-p :指定读取值的提示符
-t :指定读取值等待的时间
参数:
变量:指定读取值的变量名
实例:
[root@pier shells]# read -t 5 -p "请在五秒内输入名字:" NAME
请在五秒内输入名字:jiu
[root@pier shells]# echo $NAME
jiu
函数
系统函数
basename:获取路径的最后的文件名
dirname : 获取文件的上一层的绝对路径
[root@pier shells]# basename root/shells/
shellss
[root@pier shells]# dirname /root/shells/cash.sh
/root/shells
自定义函数
基本语法
[function] funname[()]
Action;#执行或计算的任务
[return int;]
#调用函数
funname
定义函数:
使用1
#/bin/bash
#定义函数
total=0
function sum()
total=$[$1+$2];
#注意:这里返回的值不能超过0-255,
#一旦操过,会返回对255取余的值
return $total;
#read 输入参数
read -t 5 -p "请输入第一个数字:" n1
read -t 5 -p "请输入第二个数字:" n2
#调用函数
sum $n1 $n2
#输出结果
echo "sum=$?"
测试:
[root@pier shells]# ./fun.sh
请输入第一个数字:2
请输入第二个数字:43
sum=45
[root@pier shells]# ./fun.sh
请输入第一个数字:100
请输入第二个数字:500
sum=88
**小问题:**那我们输出的结果应该是600,但是是88是对256取余的结果。我们应该怎么解决呢?
我们既然知道了是
return $total;
的问题,那么我们便不要这一句,直接注释掉。再在最后的输出是,将输出的结果编程echo "sum=$total"
就可以了。
[root@pier shells]# ./fun.sh
请输入第一个数字:100
请输入第二个数字:500
sum=600
注:shell编程并不是很适合计算,因此我们尽量只在里面写逻辑关系,运算交给擅长的工具来。
Shell工具
cut
cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。
基本语法
-
cut [选项参数] filename
说明:默认分隔符是制表符
选项参数说明
选项参数 | 功能 |
---|---|
-f | 列号,提取第几列 |
-d | 分隔符,按照指定分隔符分割列 |
-c | 指定具体的字符 |
案例
- 1)数据准备
[root@pier shells]$ cat cut.txt
dong shen
guan zhen
wo wo
lai lai
le le
- 2)切割cut.txt第一列
[root@pier shells]$ cut -d " " -f 1 cut.txt
dong
guan
wo
lai
le
- 3)切割cut.txt第二、三列
[root@pier shells]$ cut -d " " -f 2,3 cut.txt
shen
zhen
wo
lai
le
- 4)在cut.txt文件中切割出guan
[root@pier shells]$ cat cut.txt | grep "guan" | cut -d " " -f 1
guan
- 5)选取系统PATH变量值,第2个“:”开始后的所有路径:
[root@pier shells]$ echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/atguigu/bin
[root@pier shells]$ echo $PATH | cut -d: -f 2-
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/atguigu/bin
- 6)切割每一行的第一个字母(这里中文也是一个字符)
[root@pier shells]# cut -c 1 cut.txt
d
g
w
l
l
- 7)切割ifconfig 后打印的IP地址
[root@pier shells]# ifconfig | grep netmask | awk -F "inet " 'print $2' | awk -F " " 'print $1'
192.168.40.100
127.0.0.1
192.168.122.1
awk
概述
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
基本用法
awk [选项参数] ‘pattern1action1 pattern2action2…’ filename
pattern:表示AWK在数据中查找的内容,就是匹配模式
action:在找到匹配内容时所执行的一系列命令
选项参数说明
选项参数 | 功能 |
---|---|
-F | 指定输入文件折分隔符 |
-v | 赋值一个用户定义变量 |
案例
(1)数据准备
[root@pier shells]$ sudo cp /etc/passwd ./
(2)搜索passwd文件以root关键字开头的所有行,并输出该行的第7列。
[root@pier shells]$ awk -F: '/^root/print $7' passwd
/bin/bash
(3)搜索passwd文件以root关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”号分割。
[root@pier shells]$ awk -F: '/^root/print $1","$7' passwd
root,/bin/bash
注意:只有匹配了pattern的行才会执行action
(4)只显示/etc/passwd的第一列和第七列,以逗号分割,且在所有行前面添加列名user,shell在最后一行添加"dahaige,/bin/zuishuai"。
[root@pier shells]$ awk -F : 'BEGINprint "user, shell" print $1","$7 ENDprint "dahaige,/bin/zuishuai"' passwd
user, shell
root,/bin/bash
bin,/sbin/nologin
。。。
atguigu,/bin/bash
dahaige,/bin/zuishuai
注意:BEGIN 在所有数据读取行之前执行;END 在所有数据执行之后执行。
(5)将passwd文件中的用户id增加数值1并输出
[root@pier shells]$ awk -v i=1 -F: 'print $3+i' passwd
1
2
3
4
awk的内置变量
变量 | 说明 |
---|---|
FILENAME | 文件名 |
NR | 已读的记录数(行数) |
NF | 浏览记录的域的个数(切割后,列的个数) |
案例:
- 统计passwd文件名,每行的行号,每行的列数
[root@pier shells]# awk -F: 'print "filename:" FILENAME ", 行号:" NR ",列号:" NF' passwd
filename:passwd, 行号:1,列号:7
filename:passwd, 行号:2,列号:7
filename:passwd, 行号:3,列号:7
filename:passwd, 行号:4,列号:7
2)切割IP
[root@pier shells]# ifconfig | grep netmask | awk -F "inet " 'print $2' | awk -F " " 'print $1'
192.168.40.100
127.0.0.1
192.168.122.1
sort
sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出。
1)基本语法
sort(选项)(参数)
选项 | 说明 |
---|---|
-n | 依照数值的大小排序 |
-r | 以相反的顺序来排序 |
-t | 设置排序时所用的分隔字符 |
-k | 指定需要排序的列 |
参数:指定待排序的文件列表
2)案例实操
(1)数据准备
[root@pier shells]$ touch sort.sh
[root@pier shells]$ vim sort.sh
bb:40:5.4
bd:20:4.2
xz:50:2.3
cls:10:3.5
ss:30:1.6
(2)按照“:”分割后的第三列倒序排序。
[root@pier shells]$ sort -t : -nrk 3 sort.sh
bb:40:5.4
bd:20:4.2
cls:10:3.5
xz:50:2.3
ss:30:1.6
正则表达式
含义:
正则表达式是用于描述字符排列和匹配模式的一种语法规则. 它主要用于字符串的模式分割、匹配、查找及替换操作.
特殊使用;
注:这里我们学习前找一份文件,做测试。没有用文件的小伙伴,可以学我,
cp /etc/passwd ./
,复制过来一份,但是不要去修改源文件,万一。。。嗯,就哦豁!
- 正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。grep、awk、sed 等命令可以支持正则表达式。
- 通配符用来匹配符合条件的文件名,通配符是完全匹配。ls、find、cp 这些命令不支持正则表达式,所以只能使用 shell 自己的通配符来进行匹配了。
^匹配以什么什么字符开头的一行:cat passwd | grep ^a
* 匹 配 以 什 么 什 么 字 符 结 尾 的 一 行 ∗ : ‘ c a t p a s s w d ∣ g r e p t 匹配以什么什么字符结尾的一行*:`cat passwd | grep t 匹配以什么什么字符结尾的一行∗:‘catpasswd∣grept`
匹配空行就可以这么写了: ^t$
.匹配任意一个字符:cat passwd | grep r..t
注:这就是匹配r和t之间相隔两个字符的句子,中间又几个点就代表相隔字符。
*不单独使用,和他左边的第一个字符连用,表示匹配上一个字符0次或者多次:cat passwd | grep ro*t
这个就会匹配到只要包含rt,或者rt之间仅有o字符的的所有单词所在的那一行。
特殊字符[]:
-
表示匹配某个范围内的一个字符,例如
-
[6,8]------匹配6或者8
-
[a-z]------匹配一个a-z之间的字符
-
[a-z]*-----匹配任意字母字符串
-
[a-c, e-f]-匹配a-c或者e-f之间的任意字符
-
[root@pier shells]$ cat /etc/passwd | grep r[a,b,c]*t
案例
匹配所有包含n或者包含c的句子。
[root@pier shells]# cat if.sh | grep [n,c]
#!/bin/bash
then
echo "请传参!"
then
echo "大数据,我来了!!!"
then
echo "大数据,pier又回归!!!"
echo "都不留爷,pier要离开了!"
特殊字符:
有些特殊字符又特殊含义,所以在使用时需要加\\才可以正常的使用。并使用单引号引起来。
注意:shell编程虽然不难,也许一天就吃了个七七八八,但是也得要多加练习呀,一起加油呀,学会了,就等待着和pier一起进入快乐的Hadoop吧!
以上是关于shell编程的主要内容,如果未能解决你的问题,请参考以下文章