2019年12月16日shell 笔记
一、Shell中的数组
创建数组:
空数据: arr=()
Shell 数组用括号表示,元素用”空格”分割开
格式:非空数据: arr=(1 2 3 4) (带值;元素以空格分割)
注意: 往数组里添加值,数组的长度自动增长
实例:
创建空数据:
[heyali@jinghang ~]$ arr=()
创建非空数据:直接赋值
第一种:[heyali@jinghang ~]$ arr=(1 3 4 5 6 7)
第二种:下标定义数组
[heyali@jinghang ~]$ arr1=()
[heyali@jinghang ~]$ arr1[0]=1
[heyali@jinghang ~]$ arr1[1]=2
[heyali@jinghang ~]$ arr1[2]=3
[heyali@jinghang ~]$ arr1[3]=4
读取数组:
1、[heyali@jinghang ~]$ echo ${arr[1]}
3
2、
[heyali@jinghang ~]$ bash arry.sh
a
b
c
d
e
hello
word
3、
[heyali@jinghang ~]$ chmod +x arr2.sh
[heyali@jinghang ~]$ ./arr2.sh
获取数组中所有元素:
使用或@可以获取数组中所有元素
1、
[heyali@jinghang ~]$ echo ${arr1[]}
1 2 3 4
2、
[heyali@jinghang ~]$ echo ${arr1[@]}
1 2 3 4
获取数组长度:(* 或 @ 都可以)
获取数组长度的方法与获取字符串长度的方法相同
[heyali@jinghang ~]$ echo ${#arr1[*]}
4
遍历数组:
“hello word”:字符串要用双引号引起来
#!/bin/bash
arr1=(a b c d e “hello word”)
for i in ${arr1[]}
do
echo $i
done
echo ${#arr1[]}
二、运算符
(1)“
(
(
运
算
式
)
)
”
或
“
((运算式))”或“
((运算式))”或“[运算式]” + , - , *, /, % 加,减,乘,除,取余
(2)expr + , - , *, /, % 加,减,乘,除,取余
注意:expr运算符间要有空格
第一种:(())
[heyali@jinghang ~]$ a=1
[heyali@jinghang ~]$ b=2
[heyali@jinghang ~]$ echo
(
(
((
((b-
a
)
)
1
[
h
e
y
a
l
i
@
j
i
n
g
h
a
n
g
]
a)) 1 [heyali@jinghang ~]
a))1[heyali@jinghang ] echo
(
(
((
((b+
a
)
)
3
[
h
e
y
a
l
i
@
j
i
n
g
h
a
n
g
]
a)) 3 [heyali@jinghang ~]
a))3[heyali@jinghang ] echo
(
(
((
((b*
a
)
)
2
[
h
e
y
a
l
i
@
j
i
n
g
h
a
n
g
]
a)) 2 [heyali@jinghang ~]
a))2[heyali@jinghang ] echo
(
(
((
((b/
a
)
)
22
、
第
二
种
[
]
[
h
e
y
a
l
i
@
j
i
n
g
h
a
n
g
]
a)) 2 2、第二种 [] [heyali@jinghang ~]
a))22、第二种[][heyali@jinghang ] echo
[
[
[b*$a]
2
(1)expr:一步完成计算
[heyali@jinghang ~]$ expr expr 2 + 3
* 4
20
(2)采用
[
运
算
式
]
方
式
[
h
e
y
a
l
i
@
j
i
n
g
h
a
n
g
]
[运算式]方式 [heyali@jinghang ~]
[运算式]方式[heyali@jinghang ] S=
[
(
2
+
3
)
∗
4
]
[
h
e
y
a
l
i
@
j
i
n
g
h
a
n
g
]
[(2+3)*4] [heyali@jinghang ~]
[(2+3)∗4][heyali@jinghang ] echo $S
20
小数之间的运算(scale 小数点后几位,只对除法有效)
[heyali@jinghang ~]$ b=1.33
[heyali@jinghang ~]$ c=5
[heyali@jinghang ~]$ echo $(echo “scale=1;
b
/
b/
b/c” | bc)
.2
三、条件判断
1、基础语法:
[ condition ](注意condition前后要有空格)
注意:条件非空即为true,[ jinghnag ]返回true,[] 返回false。
[heyali@jinghang ~]$ [ 1 ]
[heyali@jinghang ~]$ echo
?
0
[
h
e
y
a
l
i
@
j
i
n
g
h
a
n
g
]
? 0 [heyali@jinghang ~]
?0[heyali@jinghang ] echo $?
1
2、常用判断条件
(1)两个整数之间比较
= 字符串比较
-lt 小于(less than) -le 小于等于(less equal)
-eq 等于(equal) -gt 大于(greater than)
-ge 大于等于(greater equal) -ne 不等于(Not equal)
(2)按照文件权限进行判断
-r 有读的权限(read) -w 有写的权限(write)
-x 有执行的权限(execute)
(3)按照文件类型进行判断
-f 文件存在并且是一个常规的文件(file)
-e 文件存在(existence) -d 文件存在并是一个目录(directory)
实例:
-ge 大于等于(greater equal)
[heyali@jinghang ~]$ [ 23 -ge 22 ]
[heyali@jinghang ~]$ echo $?
0
-w 有写的权限(write)(arry.sh是否有写的权限)
[heyali@jinghang ~]$ [ -w arry.sh ]
[heyali@jinghang ~]$ echo $?
0
/home/jinghang/cls.txt 目录中的文件是否存在
[heyali@jinghang ~]$ [ -e /home/jinghang/cls.txt ]
[heyali@jinghang ~]$ echo $?
1
多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)
[heyali@jinghang ~]$ [ condition ] && echo OK || echo notok
OK
[heyali@jinghang ~]$ [ condition ] && [ ] || echo notok
notok
四、流程控制
If判断:
1.基本语法
if [ 条件判断式 ];then
程序
fi
或者
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
else
程序
fi
注意事项:
(1)[ 条件判断式 ],中括号和条件判断式之间必须有空格
(2)if后要有空格
如果aaa.txt文件存在,往文件中写入bbb,如果不存在,创建aaa.txt文件,往文件中写入bbb
#!/bin/bash
if [ -f aaa.txt ]
then
echo “该文件存在”
echo “bbb” >> aaa.txt
else
echo “该文件不存在”
touch aaa.txt
echo “bbb” >> aaa.txt
fi
注意:if和elif后需要有空格
Case语句
基本语法:
case
变
量
名
i
n
"
值
1
"
)
如
果
变
量
的
值
等
于
值
1
,
则
执
行
程
序
1
;
;
"
值
2
"
)
如
果
变
量
的
值
等
于
值
2
,
则
执
行
程
序
2
;
;
…
省
略
其
他
分
支
…
∗
)
如
果
变
量
的
值
都
不
是
以
上
的
值
,
则
执
行
此
程
序
;
;
e
s
a
c
注
意
事
项
:
1
)
c
a
s
e
行
尾
必
须
为
单
词
“
i
n
”
,
每
一
个
模
式
匹
配
必
须
以
右
括
号
“
)
”
结
束
。
2
)
双
分
号
“
;
;
”
表
示
命
令
序
列
结
束
,
相
当
于
j
a
v
a
中
的
b
r
e
a
k
。
3
)
最
后
的
“
∗
)
”
表
示
默
认
模
式
,
相
当
于
j
a
v
a
中
的
d
e
f
a
u
l
t
。
注
意
:
c
a
s
e
相
当
于
j
a
v
a
中
的
s
w
i
t
c
h
"
1
"
)
相
当
于
s
w
i
t
c
h
中
的
c
a
s
e
"
1
"
:
∗
)
相
当
于
s
w
i
t
c
h
中
的
d
e
f
a
u
l
t
;
;
相
当
于
s
w
i
t
c
h
相
当
于
b
r
e
a
k
结
尾
e
s
a
c
实
例
:
输
入
一
个
数
字
,
如
果
是
1
,
则
输
出
y
i
n
y
e
,
如
果
是
2
,
则
输
出
c
l
s
,
如
果
是
其
它
,
输
出
t
i
y
u
。
[
h
e
y
a
l
i
@
j
i
n
g
h
a
n
g
]
变量名 in "值1") 如果变量的值等于值1,则执行程序1 ;; "值2") 如果变量的值等于值2,则执行程序2 ;; …省略其他分支… *) 如果变量的值都不是以上的值,则执行此程序 ;; esac 注意事项: 1)case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。 2)双分号“;;”表示命令序列结束,相当于java中的break。 3)最后的“*)”表示默认模式,相当于java中的default。 注意:case 相当于java中的switch "1") 相当于switch 中的 case "1": *) 相当于switch 中的default ;; 相当于switch 相当于break 结尾 esac 实例: 输入一个数字,如果是1,则输出yinye,如果是2,则输出cls,如果是其它,输出tiyu。 [heyali@jinghang ~]
变量名in"值1")如果变量的值等于值1,则执行程序1;;"值2")如果变量的值等于值2,则执行程序2;;…省略其他分支…∗)如果变量的值都不是以上的值,则执行此程序;;esac注意事项:1)case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。2)双分号“;;”表示命令序列结束,相当于java中的break。3)最后的“∗)”表示默认模式,相当于java中的default。注意:case相当于java中的switch"1")相当于switch中的case"1":∗)相当于switch中的default;;相当于switch相当于break结尾esac实例:输入一个数字,如果是1,则输出yinye,如果是2,则输出cls,如果是其它,输出tiyu。[heyali@jinghang ] vim case.sh
[heyali@jinghang ~]$ chmod 777 case.sh
[heyali@jinghang ~]$ ./case.sh
tiyu
[heyali@jinghang ~]$ ./case.sh 1
yinyue
for循环
基本语法:
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
实例:从1加到100
[heyali@jinghang ~]$ vim if3.sh
[heyali@jinghang ~]$ touch for.sh
[heyali@jinghang ~]$ vim for.sh
[heyali@jinghang ~]$ chmod 777 for.sh
[heyali@jinghang ~]$ ./for.sh
5050
基本语法2
for 变量 in 值1 值2 值3…
do
程序
done
实例:打印所有输入参数
[heyali@jinghang ~]$ touch for2.sh
[heyali@jinghang ~]$ vim for2.sh
[heyali@jinghang ~]$ chmod 777 for2.sh
[heyali@jinghang ~]$ bash for2.sh cls xz bd
yinyue cls
yinyue xz
yinyue bd
比较
∗
和
*和
∗和@区别
∗
和
*和
∗和@都表示传递给函数或脚本的所有参数,不被双引号“”包含时,都以$1
2
…
2 …
2…n的形式输出所有参数。
[heyali@jinghang ~]$ bash for1.sh cls xz bd
yinyue cls
yinyue xz
yinyue bd
yinyue cls
yinyue xz
yinyue bd
当它们被双引号“”包含时,“$*”会将所有的参数作为一个整体,以“$1
2
…
2 …
2…n”的形式输出所有参数;“$@”会将各个参数分开,以“$1” “
2
”
…
”
2”…”
2”…”n”的形式输出所有参数。
[heyali@jinghang ~]$ bash for1.sh cls xz bd
yinyue cls xz bd
yinyue cls
yinyue xz
yinyue bd
While循环
基本语法:
while [ 条件判断式 ]
do
程序
done
实例:从1加到100
[heyali@jinghang ~]$ touch while.sh
[heyali@jinghang ~]$ vim while.sh
[heyali@jinghang ~]$ chmod 777 while.sh
[heyali@jinghang ~]$ ./while.sh
5050
五、read读取控制台输入
基本语法:
read(选项)(参数)
选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)。
参数
变量:指定读取值的变量名
实例:
提示7秒内,读取控制台输入的名称
[heyali@jinghang ~]$ touch read.sh
[heyali@jinghang ~]$ vim read.sh
[heyali@jinghang ~]$ chmod 777 read.sh
#!/bin/bash
read -t 7 -p “Enter your name in 7 seconds” NAME
echo
N
A
M
E
[
h
e
y
a
l
i
@
j
i
n
g
h
a
n
g
]
NAME [heyali@jinghang ~]
NAME[heyali@jinghang ] ./read.sh
Enter your name in 7 seconds qqqqqq
六、函数
系统函数:
1、basename基本语法
basename [string / pathname] [suffix] (功能描述:basename命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。
选项:
suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉。
实例:
截取该/home/jinghnag/banzhang.txt路径的文件名称
[heyali@jinghang ~]$ basename /home/jinghang/a.txt
a.txt
[heyali@jinghang ~]$ basename /home/jinghang/a.txt .txt
a
2、dirname基本语法
dirname 文件绝对路径 (功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分))
实例:获取banzhang.txt文件的路径
[heyali@jinghang ~]$ dirname /home/jinghang/a.txt
/home/jinghang
自定义函数
基本语法:
[ function ] funname[()]
{
Action;
[return int;]
}
funname
注意:(1)必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先编译。
(2)函数返回值,只能通过
?
系
统
变
量
获
得
,
可
以
显
示
加
:
r
e
t
u
r
n
返
回
,
如
果
不
加
,
将
以
最
后
一
条
命
令
运
行
结
果
,
作
为
返
回
值
。
r
e
t
u
r
n
后
跟
数
值
n
(
0
−
255
)
实
例
:
[
h
e
y
a
l
i
@
j
i
n
g
h
a
n
g
]
?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255) 实例: [heyali@jinghang ~]
?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0−255)实例:[heyali@jinghang ] touch fun.sh
[heyali@jinghang ~]$ vim fun.sh
#!/bin/bash
function sum()
{
s=0
s=$[ $1 +
2
]
e
c
h
o
"
2 ] echo "
2]echo"s"
}
read -p "please input the number1: " n1;
read -p "please input the number2: " n2;
sum $n1
n
2
;
[
h
e
y
a
l
i
@
j
i
n
g
h
a
n
g
]
n2; [heyali@jinghang ~]
n2;[heyali@jinghang ] chmod 777 fun.sh
[heyali@jinghang ~]$ ./fun.sh
please input the number1: 2
please input the number2: 8
10
七、shell工具(文本处理工具)
1、Cut
cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。
基本数据:
cut [选项参数] filename
说明:默认分隔符是制表符
选项参数:
选项参数 功能
-f 列号,提取第几列
-d 分隔符,按照指定分隔符分割列
-c 指定具体的字符
实例:
准备数据:
[heyali@jinghang ~]$ touch cut.txt
[heyali@jinghang ~]$ vim cut.txt
切割cut.txt 第一列
[heyali@jinghang ~]$ cut -d " " -f 1 cut.txt
zhong
ying
feng
tian
ming
切割cut.txt第二、三列
[heyali@jinghang ~]$ cut -d " " -f 2,3 cut.txt
guo
guo
jing
yuan
mei
在cut.txt文件中切割出guo
[heyali@jinghang ~]$ cat cut.txt | grep “guo” | cut -d " " -f 1
zhong
ying
2、sed
sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
基本用法:
sed [选项参数] ‘command’ filename
选项参数说明:
选项参数 功能
-e 直接在指令列模式上进行sed的动作编辑。
-i 直接编辑文件
命令功能描述:
命令 功能描述
a 新增,a的后面可以接字串,在下一行出现
d 删除
s 查找并替换
实例:
数据准备:
[heyali@jinghang ~]$ touch sed.txt
[heyali@jinghang ~]$ vim sed.txt
zhong guo
ying guo
mei guo
ai ji
yin du
zhi li
将“mei nv”这个单词插入到sed.txt第二行下,打印
[heyali@jinghang ~]$ sed ‘2a mei nv’ sed.txt
zhong guo
ying guo
mei nv
mei guo
ai ji
yin du
zhi li
[heyali@jinghang ~]$ cat sed.txt
zhong guo
ying guo
mei guo
ai ji
yin du
zhi li
文件并没有改变
删除sed.txt文件所有包含ai的行
[heyali@jinghang ~]$ sed ‘/ai/d’ sed.txt
zhong guo
ying guo
mei guo
yin du
zhi li
将sed.txt文件中zhi替换为ni
[heyali@jinghang ~]$ sed ‘s/zhi/ni/g’ sed.txt
zhong guo
ying guo
mei guo
ai ji
yin du
ni li
注意:‘g’表示global,全部替换
将sed.txt文件中的第二行删除并将mei替换为ni
[heyali@jinghang ~]$ sed -e ‘2d’ -e ‘s/mei/ni/g’ sed.txt
zhong guo
ni guo
ai ji
yin du
zhi li
3、awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
基本用法:
awk [选项参数] ‘pattern1{action1} pattern2{action2}…’ filename
pattern:表示AWK在数据中查找的内容,就是匹配模式
action:在找到匹配内容时所执行的一系列命令
选项参数:
选项参数 功能
-F 指定输入文件折分隔符
-v 赋值一个用户定义变量
正则表达式
. 匹配除了换行符之外的任意字符
\d 匹配数字0-9 => [0-9]
\D 匹配非数字 => [^0-9]
\s 匹配空白字符(空格 \t \n …)
\S 匹配非空白字符
\w 匹配单词字符([a-zA-Z0-9_])
\W 匹配非单词字符
^ 匹配以…开头
$ 匹配结尾
多字符匹配(贪婪匹配)
.* 匹配*号前的字符任意次数 aaabbbccc a*?
.+ 匹配+号前的字符至少一次
.? 匹配?号前的字符0~1次
多字符匹配(非贪婪匹配)
.*?
.+?
.??
其他
|
() 分组
实例:
数据准备:
命令:
cat passwd | awk -F : ‘/^root/{print $1"-"$3}’
结果:
root-0
cat passwd | awk -F : '/^root|^jinghang/{print $1"-"$3}'
root-0
jinghang-500
cat passwd | awk -F : '/^root/{print $1"-"$3} /^jinghang/{print $1"-"$3}'
root-0
jinghang-500
awk -F : 'BEGIN{sum=0}{sum+=1;print $1","sum}END{print sum}' passwd
awk -F : '$3 > 100' passwd
awk -v sum=0 -F : '{sum+=1;print $1","sum}END{print sum}' passwd
awk内置变量的使用
FILENAME 文件名
NR 已读的记录数
NF 浏览记录的域的个数(切割后,列的个数)
awk -F : '{print "filename:"FILENAME",lines:"NR",colums:"NF}' passwd
使用awk提取ip地址
cat if | grep Bcast | awk -F : '{print $2}' | awk -F " " '{print $1}'
获取文件空行的行号
cat if | awk '/^$/{print NR}'
获取文件空行的总行数
cat if | awk '/^$/{print NR}' | wc -l
4、sort
sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出。
基本语法:
sort(选项)(参数)
选项 说明
-n 依照数值的大小排序
-r 以相反的顺序来排序
-t 设置排序时所用的分隔字符
-k 指定需要排序的列
参数:指定待排序的文件列表
实例:
准备数据:
[heyali@jinghang ~]$ touch sort.sh
[heyali@jinghang ~]$ vim sort.sh
bb:40:5.4
bd:20:4.2
xz:50:2.3
cls:10:3.5
ss:30:1.6
按照“:”分割后的第三列倒序排序。
[heyali@jinghang ~]$ 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
题:
问题1:获取随机字符串(8位)
答案:
[jinghnag@hadoop101 datas]$ echo $RANDOM |md5sum |cut -c 1-8
问题1:使用Linux命令查询file1中空行所在的行号
答案:
[jinghnag@hadoop101 datas]$ awk '/^
/
p
r
i
n
t
N
R
′
s
e
d
.
t
x
t
5
问
题
2
:
有
文
件
c
h
e
n
g
j
i
.
t
x
t
内
容
如
下
:
张
三
40
李
四
50
王
五
60
使
用
L
i
n
u
x
命
令
计
算
第
二
列
的
和
并
输
出
[
j
i
n
g
h
n
a
g
@
h
a
d
o
o
p
101
d
a
t
a
s
]
/{print NR}' sed.txt 5 问题2:有文件chengji.txt内容如下: 张三 40 李四 50 王五 60 使用Linux命令计算第二列的和并输出 [jinghnag@hadoop101 datas]
/printNR′sed.txt5问题2:有文件chengji.txt内容如下:张三40李四50王五60使用Linux命令计算第二列的和并输出[jinghnag@hadoop101datas] cat chengji.txt | awk -F " " ‘{sum+=$2} END{print sum}’
150
问题1:Shell脚本里如何检查一个a.txt文件是否存在?如果不存在则创建,并写入aaa?
#!/bin/bash
if [ -f a.txt ]; then
echo “文件存在!”
else
echo “文件不存在!”
echo “aaa” >> a.txt
问题1:用shell写一个脚本,对文本中无序的一列数字排序
[jinghnag@hadoop101 ~]$ cat test.txt
9
8
7
6
5
4
3
2
10
1
[jinghnag@hadoop101 ~]$ sort -n test.txt|awk '{a+=$0;print KaTeX parse error: Expected 'EOF', got '}' at position 2: 0}̲END{print "SUM=… sort -n test.txt | awk 'BEGAIN{a=0}{a+=$0;print KaTeX parse error: Expected 'EOF', got '}' at position 2: 0}̲END{print "SUM=… grep -r “shen” /home | cut -d “:” -f 1
/home/jinghnag/datas/sed.txt
/home/jinghnag/datas/cut.txt